JAVA的final关键词可以用在三方面,一是字段,二是方法,三是类,本文主要讨论final字段的几种初始化方法。
首先用我个人通俗语言来解释一下final字段的意思,就是final如果初始化值,就不允许对它进行赋值运算,不允许再修改它的值了,JAVA术语叫final字段为常量。
[ 注:本文的示例代码都没有写main方法,但代码都可以编译通过,自己可以再建一个类来进行测试。 ]
第一种情况是最常用的,就是在声明一个常量,并初始化它的值。
public class Test{
final int i=0; //在声明时就初始始常量的值.
}
第二种情况就是声明常量时,不初始化它的值,通过构造方法或块来初始化。
1.通过构造方法来初始化。
public class Test {
final int i; // 声明时未初始化,如果常量不通过构造方法或块初始化会报错的
Test() {
i = 1; // 通过默认的无参构造方法初始化i=1,
// 如果只有默认的无参构造方法,这样每个对象的fianl常量都为一个值
}
// or
Test(int n) {
i = n; // 通过构造方法重载,用有参的构造方法的参数来初始化常量为你想要的值
// 这样每个对象的i属性可以为不同的值
}
}
2.通过块来初始化常量。
public class Test {
final int i;
{
i = 1; // 这样初始化每一个对象的i属性都是1,以后不可以改它的值为其它
// 不可以再在构造函数里初始化i的值,因为块已经把常量初始化了,再初始化就是修改它的值
}
}
3.初始化静态常量。
public class Test {
static final int i;
static {
i = 1;
}
}
静态常量比较特别,不能通过构造方法或非静态块来进行初始化;从设计角度来考虑,如果可以通过构造方法或非静态块来进行初始化,那每new一个对象都会对静态的常量进行再一次的赋值操作,也就是说修改它的值,这样与常量不能修改的意思相冲突。
一个类的静态属性是所有对象公有的,而非静态属性是每一个对象私有的,所以我们只能用静态块对static常量初始化,或通过声明时就初始化;而非静态常量可以构造方法、块、声明时初始化三种初始化方法。
从成员的初始化顺序来考虑这个问题,当直接通过类名.属性或类名.方法名这样的方式访问,都会自动先调用static块,然后再调用静态属性;如果是直接调用静态方法,最后才进行静态方法的调用,而以后直接”类名.”访问时,都不会再调用static块,因为静态的是共享的,只用初始化一次。
扩展一下,从这里大家能够想到为什么不可以在静态方法里调用非静态成员属性吗?因为当直接通过类名.方法名调用非静态的成员属性时,有可能成员属性没有初始化,是通过构造方法new时才初始化,这样就有可能导致空引用的存在。sun程序员为了避免这种情况的发生,规定静态方法不能调用非静态属性。
本文摘自 http://hi.baidu.com/asd837660/blog/item/b2f5d111f791ef72ca80c4f2.html
分享到:
相关推荐
4. 成员字段初始化:所有基本类型(Primitive)设为它们的默认值(0 用于数字,以及 boolean 和 char 的等价设定)。 5. 实例变量初始化:一共有三种方式对实例变量进行初始化:①定义实例变量时指定初始值②非静态...
学习如何声明、初始化和操作数组是Java基础的一部分。 9. **类与对象**:面向对象是Java的核心特性。类是对象的蓝图,它定义了对象的属性(字段)和行为(方法)。通过`new`关键字实例化对象,实现面向对象编程。 ...
- **字段初始化顺序:**父类的字段必须先于子类字段初始化。 **Java继承思想的实现:** 如果不采用继承,可能会出现代码冗余的问题。例如,如果分别定义`Employee`类和`Manager`类,两者之间存在大量重复代码,因为...
a) 初始化的时机:类或接口会在首次主动使用时被初始化,包括创建类实例、调用静态方法、访问静态字段(非final)、反射、启动类等六种情况。被动使用类不会触发初始化。 b) 初始化的具体行为:执行类变量初始化...
// final空白, 必须在初始化对象的时候赋初值 public Test3(int x) { E = x; } public static void main(String[] args) { Test3 t = new Test3(2); // t.A = 101; // 编译错误, final变量的值一旦给定就...
final关键字可以确保对象的final字段都是初始化完成的,而static关键字可以保证一个线程即使在未使用其他线程同步机制的情况下也总是可以读到一个类静态变量的初始值。通过正确地使用final和static关键字,我们可以...
- `final`用于修饰变量时,该变量将变为常量,其值一旦初始化后便不能再更改。 - 如果是基本数据类型(如int, double等),那么其值不能改变;如果是引用类型(如String, Object等),则对象的引用不能改变,但...
// 实例变量,初始化后不能改变 public final void printNumber() { // 最终方法,不能被重写 System.out.println(number); } } final class ImmutableClass { // 不可继承的类 private int value; ...
### Java序列化详解 在Java开发中,序列化是一个非常重要的概念,它涉及到对象的状态转换为可以存储或传输的形式,并且能够在之后将其恢复为原始形式的过程。本文将深入探讨Java序列化的各个方面,包括其概念、原理...
当编译器遇到枚举类型时,会自动为每个枚举常量创建一个私有的构造函数,并在类的静态初始化块中创建实例。这些实例存储在静态字段中,确保它们在类加载时创建,因此枚举对象是线程安全的。例如,反编译后的 `Color...
- **final字段语义的加强**:为了支持线程安全的不可变性,JSR-133对final字段的语义进行了增强,允许开发者在不显式同步的情况下实现final字段的初始化和不可变性。这可能要求在构造函数结束时添加存储-存储屏障等...
// 初始化数组 } } public FalseSharing(final int arrayIndex) { this.arrayIndex = arrayIndex; } @Override public void run() { VolatileLong counter = longs[arrayIndex]; long i = counter.value...
`final`修饰符用来声明不可变的对象、变量或方法,一旦被初始化就不能更改。 #### 6.7 abstract修饰符 `abstract`修饰符用于声明抽象类和抽象方法,抽象类不能被实例化,只能被继承。 #### 6.8 接口 接口是一种...
- **特性**: 创建结束时,若对象被安全发布,则所有线程都可以获取到final字段在构造过程中设置的值,即使没有`synchronized`关键字。 #### 三、保护共享数据 在多线程环境中,保护共享数据至关重要,以确保数据...
19. `for`:用于定义循环,可以指定初始化、条件检查和迭代操作。 20. `if`:用于条件判断,根据条件执行不同的代码块。 21. `implements`:声明一个类实现一个或多个接口,强制类实现接口中定义的所有方法。 22....
- 子类没有自动调用父类的构造器,需要通过`super()`语句显式调用,确保父类的初始化。 - 如果子类没有定义构造器,编译器会为它添加一个默认构造器,这个构造器会自动调用父类的无参构造器。 4. 方法的继承与...
4. 抽象类的构造方法可以在子类的构造方法中被调用,用于初始化子类实例。 接口(Interface)是另一种形式的抽象,它只包含常量和抽象方法。接口提供了一种方式来定义一组方法,而无需提供实现。类可以实现多个接口...
枚举还可以有构造函数,允许在初始化时传递参数,创建更复杂的枚举实例。同时,枚举支持继承,可以扩展自`Enum`类,实现自定义的行为。枚举还支持常量的排序,可以通过`ordinal()`方法获取枚举常量在枚举类型中的...
在第16章中,我们将深入探讨Java类加载、连接和初始化的过程,以及反射的相关概念。 1. **类的加载、连接和初始化** 类加载是Java运行时环境为了使用类而进行的第一步。当程序首次主动使用一个类时,如果该类尚未...
5. **类的加载过程、实例化、继承、多态**:深入理解类的生命周期,包括加载、验证、准备、解析和初始化。实例化是指创建对象的过程。继承允许一个类(子类)从另一个类(父类)继承属性和行为。多态是面向对象的...