标签: java-record

为什么 Java 记录的规范构造函数不能具有比记录级别更严格的访问权限?

我有一种情况,我希望特定类型的记录实例只能使用同一包内单独类中的工厂方法创建。这样做的原因是因为在创建记录之前我需要执行大量的验证。

记录旨在成为其验证字段的哑数据载体,但验证不能在记录的构造函数中进行,因为我们需要访问一些精心设计的验证器对象才能实际执行验证。

由于将验证器对象传递给记录构造函数意味着它们将构成记录状态的一部分,这意味着我们不能使用记录构造函数来执行记录的验证。

因此,我将验证提取到它自己的工厂中并编写了如下代码(工厂类和同一包中的记录):

package some.package;

// imports.....

@Component
class SomeRecordFactory {
    private final SomeValidator someValidator;
    private final SomeOtherValidator someOtherValidator;
    // Rest of the fields
    // ....

    // constructor  
    // ....


    public SomeRecord create(...) {
         someValidator.validate(....);
         someOtherValidator.validate(....);
         // .... other validation

         return new SomeRecord(...);
    }
}
Run Code Online (Sandbox Code Playgroud)
package some.package;

public record SomeRecord(...) {
    /* package-private */ SomeRecord {
    }
}
Run Code Online (Sandbox Code Playgroud)

无论出于何种原因,上述内容不适用于 IntelliJ 抱怨:

Compact constructor access level cannot be more restrictive than the record access level (public)
Run Code Online (Sandbox Code Playgroud)

我可以通过使用普通类(允许使用单个包私有构造函数)来避免这个问题,但希望更准确地将数据建模为记录。

为什么记录存在此限制?未来是否有取消此限制的计划?

java java-record java-16

7
推荐指数
3
解决办法
523
查看次数

为什么 RecordComponent 没有 Java 17 中 Records 类中定义的注释信息?

我摆弄唱片,发现一些对我来说看起来不合逻辑的东西:

记录:

record R(@NotEmpty Integer i) {}
Run Code Online (Sandbox Code Playgroud)

代码:

RecordComponent[] recordComponents = R.class.getRecordComponents();
System.out.println(recordComponents[0].isAnnotationPresent(NotEmpty.class));
//prints false
Run Code Online (Sandbox Code Playgroud)

但是,如果我这样做:

System.out.println(R.class.getDeclaredFields()[0].isAnnotationPresent(NotEmpty.class));
//prints true
Run Code Online (Sandbox Code Playgroud)

这是预期的吗?因为RecordComponent implements AnnotatedElement,所以我认为RecordComponent应该有关于注释的信息。我的期望是错误的吗?

java java-record java-17

7
推荐指数
1
解决办法
648
查看次数

如何将 Java 17 记录转换为 Clojure 映射?

有一个clojure.core/bean将 POJO 转换为 Map 的标准函数:

class MyPojo{
  public String getFirst(){ return "abc"; }
  public int getSecond(){ return 15; }
}

IFn bean = Clojure.var("clojure.core", "bean")

var result = bean.invoke(new MyPojo())

// result => {:first = abc, :second = 15}
Run Code Online (Sandbox Code Playgroud)

对于 Java 17 记录类,此函数不起作用,因为记录不遵循 POJO"get***"属性约定。

Clojure 是否以同样的方式支持 Java 17 记录实例?

clojure java-record java-17

7
推荐指数
1
解决办法
585
查看次数

避免 Java 记录中的 Javadoc 重复

新的 Javarecord应该会减少样板文件。我可以使用和组件快速创建一个不可变的FooBar类,而不必担心局部变量、构造函数值复制和 getter,如下所示:foobar

\n
/**\n * Foo bar record.\n */\npublic record FooBar(String foo, String bar) {\n}\n
Run Code Online (Sandbox Code Playgroud)\n

当然,我想记录记录组件是什么,这样它们就会显示在生成的 Javadoc 中!所以我添加这个:

\n
/**\n * Foo bar record.\n * @param foo That foo thing; cannot be <code>null</code>.\n * @param bar That bar thing; cannot be <code>null</code>.\n */\npublic record FooBar(String foo, String bar) {\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这很好用\xe2\x80\x94记录组件显示在文档中。

\n

除了几乎 100% 的记录之外,作为一名优秀的开发人员,我当然需要验证foobar确保它们不为空,对吧?(对。)记录很容易做到这一点:

\n
/**\n * Foo bar record.\n * @param foo That foo thing; cannot …
Run Code Online (Sandbox Code Playgroud)

java javadoc java-record

7
推荐指数
1
解决办法
322
查看次数

java记录上的构造函数注释

有没有办法获得像ConstructorProperties这样的注释,它@Target(CONSTRUCTOR)必须注释 java 16 记录的生成构造函数?例如:

@ConstructorProperties({"id", "filename"})
public record Person(long id, String filename) {}
Run Code Online (Sandbox Code Playgroud)

此 ^ 导致以下错误:

java: annotation type not applicable to this kind of declaration
Run Code Online (Sandbox Code Playgroud)

java constructor annotations java-record java-16

6
推荐指数
1
解决办法
148
查看次数

Java 记录和字段注释

当我们在 Java 中使用类时,为每个类字段/方法添加 JavaDoc/注释非常简单:

class Product {
    //Product unique identifier
    private int id;
}
Run Code Online (Sandbox Code Playgroud)

如果我们将这些类迁移到 Java 记录,则不清楚在这种情况下编写注释/JavaDocs 的最佳实践是什么:

record Product(int id, String name, double price) {
}
Run Code Online (Sandbox Code Playgroud)

因为现在所有字段都在一行中声明。

java java-14 java-record java-16

6
推荐指数
2
解决办法
209
查看次数

Spring 在 @ConfigurationProperties 的 java 记录上调用 noargs 构造函数

我在这里拔掉我的头发。我想为我的 @ConfigurationProperties 使用 Java 记录,为未指定的配置属性提供默认值。这是一个非常简单的例子:

@ConfigurationProperties(prefix = "myconfig")
public record LoggingProperties (
    String whatever,
    String somethingToDefault
) {
    
    public LoggingProperties(String whatever, String somethingToDefault) {
        this.whatever = whatever;
        this.somethingToDefault = somethingToDefault;
    }

    public LoggingProperties(String whatever) {
        this(whatever, "whatever was specified, but not somethingToDefault");
    }

    public LoggingProperties() {
        this("neither was specified", "neither was specified");
    }
}
Run Code Online (Sandbox Code Playgroud)

看来,如果我声明一个 noargs 构造函数,spring 总是会调用它,无论我的配置文件(application.yml)中实际有什么

上面将产生一个实例,记录时显示: LoggingProperties[whatever=neither was specified, somethingToDefault=neither was specified],尽管我的配置已指定。

如果我删除无参数构造函数,我会得到一个异常No default constructor found;

如果我将 @ConstructorBinding 添加到 allargs 构造函数中,我会得到: LoggingProperties[whatever=value from file, somethingToDefault=null] …

spring spring-boot configurationproperties java-record

6
推荐指数
1
解决办法
1578
查看次数

如何使用 Java Record 和数据库中的数据来填充 JavaFX TableView

简短问题:使用记录使用数据库中的数据填充 Java FX 表视图的最佳方法是什么?(而不是具有 getter 和 setter 的典型对象类)

完整的问题: 我最近创建了这个 InventoryRecord.java 文件来替换我用来填充表视图的名为“Inventory”的传统对象:

import java.util.List;

public record InventoryRecord(
        String make
        , String model
        , String officialModel
        , String upc
        , List<String> category
        , String type
        , String description
        ,String vendor
        , Double cost
        , Double price
        ) {}
Run Code Online (Sandbox Code Playgroud)

我想使用此记录作为我的框架,使用数据库中的数据填充我的 TableView(在本例中为 Neo4j,但这并不重要)

在拥有此 InventoryRecord 记录之前,我使用的是一个名为 Inventory 的典型类,如下所示(当然,为了保持问题的可读性,我已缩短它,假设 Inventory 的每个属性都有 getter/setter。)

public class Inventory {
    private String make;
    private String model;
    private String officialModel;
    private List<String> category;
    private String type;
    private String description; …
Run Code Online (Sandbox Code Playgroud)

java javafx maven controlsfx java-record

6
推荐指数
1
解决办法
91
查看次数

不允许此关键字访问记录构造函数中的字段

我有以下记录:

public record A(List<String> list) {
    public A {
      this.list = new ArrayList<>(list);
    }
}
Run Code Online (Sandbox Code Playgroud)

但我得到这个编译错误:

无法为最终变量赋值

另一方面,这可以编译:

public record A(List<String> list) {
    public A {
      list = new ArrayList<>(list);
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么是这样?

java java-record java-17

5
推荐指数
1
解决办法
695
查看次数

如何隐藏提供公共静态工厂方法的 Java 记录上的构造函数?

我用Java有这个简单的记录:

public record DatePair( LocalDate start , LocalDate end , long days ) {}
Run Code Online (Sandbox Code Playgroud)

我希望所有三个属性 ( startend、 & days) 都可供公开阅读,但我希望第三个属性 ( days) 自动计算,而不是在实例化期间传入。

所以我添加一个静态工厂方法:

public record DatePair( LocalDate start , LocalDate end , long days ) {}
Run Code Online (Sandbox Code Playgroud)

只想使用这个静态工厂方法进行实例化。我想隐藏构造函数。因此,我显式地编写了隐式构造函数,并对其进行了标记private

public record DatePair( LocalDate start , LocalDate end , long days )
{
    public static DatePair of ( LocalDate start , LocalDate end )
    {
        return new DatePair ( start , end …
Run Code Online (Sandbox Code Playgroud)

java constructor factory static-factory java-record

5
推荐指数
1
解决办法
1389
查看次数