java-常量

Java中的final关键字
本文详细介绍了Java中的final关键字,包括其在变量、方法和类上的使用方式,以及如何正确地初始化final变量。此外,还讨论了final关键字在提高程序效率和确保设计意图方面的作用。

变量和常量

在程序中存在大量的数据来代表程序的状态,其中有些数据在程序的运行过程中值会发生改变,有些数据在程序运行过程中值不能发生改变,这些数据在程序中分别被叫做变量和常量。

在实际的程序中,可以根据数据在程序运行中是否发生改变,来选择应该是使用变量代表还是常量代表。

常量代表程序运行过程中不能改变的值


java常量

Java中,用关键字final指示常量,声明方式和变量类似:

final double PI = 3.1415927;

Final关键字与static关键字同时使用,静态常量:

public static final int NUM = 1;

注意:在Java编码规范中,要求常量名大写.

关于final详解

  1. final用于声明属性(常量),方法和类。表示属性时,一旦被分配内存空间就必须初始化(不会有默认初始化,局部变量也是如此,默认初始化只有普通的非final成员属性),对于static且无final修饰的类变量,有默认的初始值。提倡声明变量后,必须初始化后方可用,这是java的安全之一.
  2. final这个关键字的含义是“这是无法改变的”或者“终态的”;
  3. 关键字final表示这个变量只能被赋值一次。一旦被赋值后,就不能够再更改了。
  4. java语言的发明者可能由于两个目的而阻止改变:
    1).效率问题:
    jdk中的某些类的某些方法,是不允许被用户覆盖的,设计者可能认为,所用方法已经是最好的方法,用户私自覆盖,或是由于疏忽而覆盖,就会影响JVM或是系统的系能;

    2). 设计所需:
    众所周知,有些情况必须使用final关键字,比如方法中的匿名内部类的参数传递
    【修饰变量】:
    final成员变量表示常量,只能被赋值一次,赋值后值不再改变。
    【修饰方法】:
    final方法不能被子类方法覆盖,但可以被继承。
    【修饰类】:
    final类不能被继承,没有子类。(如String类)

  5. 被final修饰而没有被static修饰的类的属性变量只能在两种情况下初始化:(必须初始化)
    a.在它被声明的时候赋值
    b.在构造函数里初始化

    代码块

    public class TestVar{
       public final int num;
    
       public TestVar(){
           num = 1; //在构造函数里初始化
      }
    }
    
    public class TestVar{
       public final int num = 9; //在它被声明的时候赋值
    }
    

    解释: 当这个属性被修饰为final,而非static的时候,它属于类的实例对象的资源(实例常量),当类被加载进内存的时候这个属性并没有给其分配内存空间,而只是 定义了一个变量num,只有当类被实例化的时候这个属性才被分配内存空间,而实例化的时候同时执行了构造函数,所以属性被初始化了,也就符合了当它被分配内存 空间的时候就需要初始化,以后不再改变的条件.

  6. 被static修饰而没有被final修饰的类的属性变量只能在两种情况下初始化:(可以不初始化)
    a.在它被声明的时候赋值
    b.在静态或非静态块里初始化

    代码块

    public class TestVar{
       public static int num = 1;//在它被声明的时候赋值
    }
    
    public class TestVar{
      static
     {
         int num = 1; //静态块初始化
     }
    
     {
         int num = 2;//静态块初始化
     }
    } 

    解释:
    当类的属性被同时被修饰为static时候,他属于类的资源(类变量),在类加载后,进行连接时候,分三步: 先验证;然后准备,准备时,先分配内存,接着默认初始化;可以进行解析。最后,进行类初始化,类初始化前,必须保证它的父类已经初始化了,所以最先初始化的是超类,对于接口,不必初始其父接口。类初始化时,它把类变量初始化语句及静态初始化语句放到类初始化方法中,所以,如果无此两种语句,也就没类初始化方法,而构造函数是在当类 被实例化的时候才会执行,所以用构造函数,这时候这个属性没有被初始化.程序就会报错.而static块是类被加载的时候执行,且只执行这一次,所以在 static块中可以被初始化.

  7. 同时被final和static修饰的类的属性变量只能在两种情况下初始化:(必须初始化)
    a.在它被定义的时候
    b.在类的静态块里初始化
    c.特别对于初始化时候调用抛出异常的构造函数,初始时候注意,特别是在实现单例模式时(只能这么初始化)

    代码块

    
    public class TestVar{
        public static final int num = 1;//在它被定义的时候  
    }
    
    public class TestVar{
      static
      {
        final int num = 9;//在类的静态块里初始化
      } 
    }

    解释:
    当类的属性被同时被修饰为static和final的时候,他属于类的资源(类常量),那么就是类在被加载进内存的时候(也就是应用程 序启动的时候)就要已经为此属性分配了内存,所以此时属性已经存在,它又被final修饰,所以必须在属性定义了以后就给其初始化值.而构造函数是在当类 被实例化的时候才会执行,所以用构造函数,这时候这个属性没有被初始化.程序就会报错.而static块是类被加载的时候执行,且只执行这一次,所以在 static块中可以被初始化.

java中的 final变量==常量

【final变量的变与不变】:final表示变量的值或引用不变
有人说final变量在赋值后就不可变,此变量可以是基本数据类型+String或者是对象
那么这个不变到底指的是什么呢?
这个不变指的是引用,是地址,而所引用的对象的内容仍然是可变的。注:如果为对象,注意此时类初始化条件
就是说,这个final变量永远指向某个对象,是一个常量指针,而不是指向常量的指针。

【final关键字的具体应用】:
【final+变量】:
在实际应用中,这种形式是非常少见的。
比如logger是可以的,但是貌似并不是非常实用,或许用户仍然希望通过setter来改变logger变量。
【static+final+变量】:
常量。经常使用。
【final+方法】:
JDK中常用,但是自己并未常用。
【final+类】:
helper类经常使用。
【final用于匿名内部类的参数传递】:
在多线程测试时,经常使用。
【final用于方法的参数】:
并不常用。

延伸:

在interface里面的变量都是public static final 的。所以你可以这样写:
public static final int i=10;
或则
int i=10;(可以省略掉一部分)
注意在声明的时候要给变量赋予初值

解释:
首先你要弄清接口的含义.接口就是提供一种统一的’协议’,而接口中的属性也属于’协议’中的成员.它们是公共的,静态的,最终的常量.相当于全局常量.
抽象类是不’完全’的类,相当于是接口和具体类的一个中间层.即满足接口的抽象,也满足具体的实现.
如果接口可以定义变量,但是接口中的方法又都是抽象的,在接口中无法通过行为来修改属性。有的人会说了,没有关系,可以通过实现接口的对象的行为来修改接口中的属性。这当然没有问题,但是考虑这样的情况。如果接口A中有一个public访问权限的静态变量a。按照java的语义,我们可以不通过实现接口的对象来访问变量a,通过A.a = xxx;就可以改变接口中的变量a的值了。正如抽象类中是可以这样做的,那么实现接口A的所有对象也都会自动拥有这一改变后的a的值了,也就是说一个地方改变了a,所有这些对象中a的值也都跟着变了。如果可以修改值:这和抽象类有什么区别呢,怎么体现接口更高的抽象级别呢,怎么体现接口提供的统一的协议呢,那还要接口这种抽象来做什么呢?所以接口中不能出现变量,如果有变量,就和接口提供的统一的抽象这种思想是抵触的。所以接口中的属性必然是常量,只能读不能改,这样才能为实现接口的对象提供一个统一的属性。
通俗的讲,你认为是要变化的东西,就放在你自己的实现中,不能放在接口中去,接口只是对一类事物的属性和行为更高层次的抽象。对修改关闭,对扩展(不同的实现implements)开放,接口是对开闭原则的一种体现。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值