简体   繁体   English

不可变 class:空白最终字段可能尚未初始化

[英]Immutable class: The blank final field may not have been initialized

I have to do an immutable class but I'm given a mistake.我必须做一个不可变的 class 但我犯了一个错误。

public final class ClassX{
   private final String a;
   private final String b;
   private final int c;


   public ClassX(String a, String b, int c){
       this.a=a;
       this.b=b;
       if(c>=1||c<=100)
       this.c=c;
   }

The blank final field c may not have been initialized空白的最终字段 c 可能尚未初始化

Am I doing something wrong?难道我做错了什么?

without if I don't get any errors but I need variable c to be in range 1-100如果我没有收到任何错误,但我需要变量 c 在 1-100 范围内

Balance your if with an else平衡你的ifelse

In your phrasing:在你的措辞中:

if( … ) { this.c = c ; }

… you have not addressed the negative case. ……你还没有解决负面情况。 If the test in the if test results in a false , your member field this.c will not have been assigned a value by you.如果if测试中的测试结果为false ,则您的成员字段this.c不会被您分配值。 That member field of int will be assigned a default value of zero. int的该成员字段将被分配一个默认值零。

(For object references in contrast to primitives, the default will be null . That means no value at all in that member field.) (对于与原语相反的 object 引用,默认值为null 。这意味着该成员字段中根本没有值。)

We can see this defaulting behavior in the following code example.我们可以在下面的代码示例中看到这种默认行为。

package work.basil.example;

public class DefaultingInt
{
    private int count;

    public int getCount ( ) { return this.count; }  // Getter method (accessor). 

    @Override
    public String toString ( )
    {
        return "DefaultingInt{ " +
                "count=" + count +
                " }";
    }

    public static void main ( String[] args )
    {
        DefaultingInt di = new DefaultingInt();
        System.out.println( "di = " + di );
    }
}

When run:运行时:

di = DefaultingInt{ count=0 } di = DefaultingInt{ count=0 }

With the code above, the value of the member field could always be changed later is some other code.使用上面的代码,成员字段的值总是可以在以后更改为其他代码。

final requires a value be assigned final需要赋值

Your code adds the complication of marking the member field final .您的代码增加了标记成员字段final的复杂性。 Using final means that you intend to assign a value once, as a constant.使用final意味着您打算将一个值分配一次,作为一个常量。 The compiler ensures that no code is allowed to change that value.编译器确保不允许任何代码更改该值。

Your IDE or compiler is flagging an error because in the case of your if test returning false , you will not have assigned an explicit value to the final field.您的IDE或编译器正在标记错误,因为在您的if测试返回false的情况下,您不会为final字段分配显式值。 After the constructor ends, you cannot later assign a value.构造函数结束后,您不能稍后分配值。 Since you insisted you would immediately set a single final value, and your code at runtime may miss your two chances to have set that value (static assignment, or in the constructor), the compiler knows something is wrong.由于您坚持要立即设置一个最终值,并且您的代码在运行时可能会错过两次设置该值的机会(静态赋值,或在构造函数中),编译器知道有问题。

Solution: Add else解决方案:添加else

To take care of the missing case when your if returns a false , change your code to add an else block.要在if返回false时处理丢失的情况,请更改代码以添加else块。

if( … ) { this.c = c ; } else { this.c = your-default-value-here ; }

As others pointed out, the logic of your particular if test is flawed.正如其他人指出的那样,您的特定if测试的逻辑是有缺陷的。 Use logical AND rather than OR.使用逻辑 AND 而不是 OR。

if( ( c >= 1 ) && ( c <= 100 ) )  // If input value is within the bounds allowed, assign to field.
{ 
    this.c = c ; 
} 
else // Else input value is outside the bounds allowed.
{ 
    this.c = your-default-value-here ; 
}

If you cannot specify a default value, throw an exception instead.如果您无法指定默认值,请改为引发异常。

if( ( c >= 1 ) && ( c <= 100 ) )  // If input value is within the bounds allowed, assign to field.
{ 
    this.c = c ; 
} 
else // Else input value is outside the bounds allowed. Throw exception.
{ 
    throw new  IllegalArgumentException( "Requires an input value of 1 to 100 inclusive." ) ;
}

Full example code:完整示例代码:

package work.basil.example;

public class DefaultingInt
{
    final private int count;

    public DefaultingInt ( int count )
    {
        if ( ( count >= 1 ) && ( count <= 100 ) )  // If input value is within the bounds allowed, assign to field.
        {
            this.count = count;
        } else // Else input value is outside the bounds allowed. Throw exception.
        {
            throw new IllegalArgumentException( "Requires an input value of 1 to 100 inclusive." );
        }
    }

    public int getCount ( ) { return this.count; }  // Getter method (accessor). 

    @Override
    public String toString ( )
    {
        return "DefaultingInt{ " +
                "count=" + count +
                " }";
    }

    public static void main ( String[] args )
    {
        DefaultingInt di = new DefaultingInt( 101 );
        System.out.println( "di = " + di );
    }
}

When run:运行时:

Exception in thread "main" java.lang.IllegalArgumentException: Requires an input value of 1 to 100 inclusive.线程“主”java.lang.IllegalArgumentException 中的异常:需要 1 到 100(含)的输入值。


Java record Java record

By the way, for a simple immutable object whose main job is carrying data, consider using the new records feature due to arrive in Java 16 and previewed in earlier versions.顺便说一句,对于一个主要工作是承载数据的简单不可变 object,请考虑使用新的记录功能,该功能将在 Java 16 中到达并在早期版本中预览。

You simply declare the member fields.您只需声明成员字段。 Java implicitly creates constructor, getters, and overrides of toString , equals , and hashCode . Java 隐式创建构造函数、getter 和toStringequalshashCode的覆盖。

In a record, marking final on a member field is superfluous.在记录中,在成员字段上标记final是多余的。 Every member field on record is implicitly final , a read-only constant, with an implicit getter accessor method.记录中的每个成员字段都是隐式final ,一个只读常量,具有隐式 getter 访问器方法。 A record is meant to be a non-modifiable nominal tuple (an immutable assortment of named fields).记录意味着不可修改的名义元组(命名字段的不可变分类)。 The content within an object referenced by a record's member field may be mutable as with any other class, but the assignment of that one particular object to that member field cannot be changed.记录的成员字段引用的 object的内容可能与任何其他 class 一样是可变的,但是不能更改该特定 object 到该成员字段的分配。 Primitives such as your int field are not object references, but simply the immediate value, and are immutable when used as a field in a record.诸如int字段之类的原语不是 object 引用,而只是立即值,并且在用作记录中的字段时是不可变的。

record ClassX( String a , String b , int c ) {}

You can still provide your own constructor to run your if test for data validation.您仍然可以提供自己的构造函数来运行if测试以进行数据验证。

package work.basil.example;

public record DefaultingInt(int count)
{
    public DefaultingInt ( int count )
    {
        if ( ( count >= 1 ) && ( count <= 100 ) )  // If input value is within the bounds allowed, assign to field.
        {
            this.count = count;
        } else // Else input value is outside the bounds allowed. Throw exception.
        {
            throw new IllegalArgumentException( "Requires an input value of 1 to 100 inclusive." );
        }
    }

    public static void main ( String[] args )
    {
        DefaultingInt di = new DefaultingInt( 42 );
        System.out.println( "di = " + di );
    }
}

When run:运行时:

di = DefaultingInt[count=42] di = DefaultingInt[count=42]

this.c = Math.min(100, Math.max(c,1));

Your if is useless.你的if没用。

If you want c to be in the range 1-100 you should change ||如果您希望 c 在 1-100 范围内,您应该更改|| to &&&&

If you want c to be initialised to max or min value every time you can use @A.Alexander solution如果您希望每次可以使用@A.Alexander 解决方案时都将 c 初始化为最大值或最小值

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 空白的final字段可能尚未初始化 - the blank final field may not have been initialized 空白的最终字段 INSTANCE 可能尚未初始化 - The blank final field INSTANCE may not have been initialized 空白的最终字段INITIAL可能尚未初始化 - The blank final field INITIAL may not have been initialized 空白的最终字段种子可能尚未初始化 - The blank final field seed may not have been initialized Spring io @Autowired:空白的最终字段可能尚未初始化 - Spring io @Autowired: The blank final field may not have been initialized 空白的最终字段名称可能尚未初始化错误 - The blank final field name may not have been initialized error 空白的最终字段conn可能尚未在非最终成员上初始化 - The blank final field conn may not have been initialized on a non final member 这两个构造函数上的错误 空白的最终字段 errorCodes 可能尚未初始化 - error on this two constructor The blank final field errorCodes may not have been initialized Java“空白的最终字段可能尚未初始化”匿名接口与 Lambda 表达式 - Java "The blank final field may not have been initialized" Anonymous Interface vs Lambda Expression Java“空白最终字段可能尚未初始化”方法奇怪性抛出异常 - Java “blank final field may not have been initialized” Exception thrown in method oddness
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM