第九天(上) final和static关键字

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第九天(上) final和static关键字相关的知识,希望对你有一定的参考价值。

继承的出现提高了代码的复用性,方便开发,是多态的前提,但随之而来的也有问题,有些累在描述后不想被继承,或者里面的方法功能时固定的,不想让子类重写,可子类继承之后又可以重写该怎么办呢

这个时候就需要一个关键字final  意为 最终的 不可变的

Final是一个比较强的修饰符,可以用来修饰类,类的成员,以及方法

 

Final修饰类

在类的前面加上final

Final类不可以被继承,但可以继承其他类,是个太监.其成员方法也默认为final的,但成员变量是可以改变的

 

在使用final修饰类的时候,要注意谨慎选择,除非这个类真的在以后不会用来继承或者出于安全的考虑,尽量不要将类设计为final类。

 

Final修饰方法

子类可以继承final修饰的方法,但不能重写.

 

父类中没有被final修饰的方法,子类继承后可以用final修饰

 

如果父类中final修饰的方法同时访问控制权限为private将会导致子类中不能直接继承到此方法,因此,此时可以在子类中定义相同的方法名和参数,此时不再产生重写与final的矛盾,而是在子类中重新定义了新的方法

注:类的private方法会隐式地被指定为final方法。

Final修饰局部变量:

修饰基本数据类型 

Final修饰的变量称为常量,只能赋值一次,就不会被改变即使赋的新值与旧值一样也不可以。

修饰引用数据类型

引用数据类型的值是地址值,final修饰后不可以改变地址值,但地址值所指的内容是可以改变的.

Final修饰成员变量

修饰成员变量时,成员变量需要在创建对象前复制

1直接赋值 通过等号

2构造方法中赋值 没有显式的赋值那么多个构造方法都要为其赋值

Final修饰成员变量时,固定的不是内存中的值,而是手动的赋值(成员变量是有默认值的)

Final修饰方法参数

有点懵比,查了好多没有找到一个令人信服的,说法也不一样

关于final的一些题

public class Test {

    public static void main(String[] args)  {

        String a = "hello2";

        final String b = "hello";

        String d = "hello";

        String c = b + 2;

        String e = d + 2;

        System.out.println((a == c));

        System.out.println((a == e));

        System.out.println(a.equals(e));

   }

}

结果true

false

True

为什么呢?

b被声明成了final的了,所以就是常量,常量表达式String c = b + 2;JVM会优化成String c = "hello" + 2;,这个结果是变成编译期就是已知了,指向常量池中的hello2字符串,也就是a

public class Test {

    public static void main(String[] args)  {

        String a = "hello2";

        final String b = getHello();

        String c = b + 2;

        System.out.println((a == c));

 

    }

     

    public static String getHello() {

        return "hello";

    }

}

结果:
false

这里的b虽然是常量,但是在编译期是不能获得值的,只有在运行的时候才会调用函数,初始化赋值,所以这时的String c = b+2是运行期间计算出来的,而加号连接运算符,内部则是调用的StringBuilder,然后toString,所以c相当于是new出来的String,即c是指向堆内存的地址,c内部的char数组才指向常量池中的字符串,所以明显a != c.

 

希望看了深入理解jvm虚拟机后可以更好的理解这些问题.

 

Static

定义类的时候,类中会有相应的方法和属性,而方法和属性都是通过创建本类对象调用的,当调用对象的某个方法时,这个方法又没有访问特定的数据,创建这个对戏那个就有点多余,或者说没有对象都有一模一样的常量,每new一个就出现一次这个常量,又没有办法一劳永逸呢

要解决上面的问题就要用到关键字static.

代表全局,静态的意思,用来修饰成员变量,成员方法,以及代码块.其次还有静态内部类以后有机会了解.

Static的作用: 简单来说就是方便在没有创建对象的情况下来调用方法或者变量.

Java中并不存在全局变量的概念,但我们可以用static来实现一个伪全局变量的概念,

Static修饰变量:被static修饰(只能修饰成员变量)变量称为静态变量,没有使用static修饰的叫实例变量.伴随着类的加载完成初始化.分配一次内存.每一个对象对静态变量的操作都会反应到其他对象上。

什么时候该使用static修饰呢?

当这个成员会被类的所有对象所共享,一般我们把共性的数据定义为静态变量

有什么好处呢

对象之间共享数据,访问方便,节约内存

怎么调用呢

类名.静态成员变量名

对象名.静态成员变量名       ------不建议使用该方式,会出现警告

 

Static修饰方法:static修饰的方法称为静态方法.

他在类加载的时候就存在了,它不依赖于任何实例,所以static方法必须实现,也就是说他不能是抽象方法abstract。

什么时候该使用static修饰

成员方法跟着变量走,静态方法只能访问静态变量,如果成员方法中引用了静态的其他成员,那么这个方法就要声明为静态的方法.

怎么调用

类名.静态成员方法名(参数)

对象名.静态成员方法名(参数) ------不建议使用该方式,会出现警告

注意事项:

静态方法不能操作非静态变量,也不能调用非静态方法。(这个可以这样理解:静态方法属于类,直接通过类名就可以调用,而此时可能没有任何实例,更谈不上操作实例变量和调用实例方法了。)

同理,静态也不能使用this和super关键字.

所以main方法中不能直接调用非静态的方法.

为什么mian方法时静态的

为了使在调用mian方法前不创建任何实例对象.

Static静态代码块

static修饰的代码块,我们称之为静态代码块,静态代码块会随着类的加载一块执行,而且他可以随意放,可以存在于该了的任何地方。

用来初始化静态变量。

在类加载时,在执行main方法之前执行相关操作。

没有main方法的程序可以执行吗?

Jdk1.7之前可以

之后会报错

静态导包

感觉没什么用jdk1.5之后

其目的是为了减少字符输入量,提高代码的可阅读性,以便更好地理解程序。 

采用static导入包后,在不与当前类的方法名冲突的情况下,无需使用“类名.方法名”的方法去调用类方法了,直接可以采用"方法名"去调用类方法,就好像是该类自己的方法一样使用即可。

建议对于静态导入,一定要遵循两个规则:

 

1.不要使用*(星号)通配符,除非是导入静态常量(只包含常量的类或接口)。

 

2. 方法名是具有明确、清晰表象意义的工具类。

静态内部类

内部类了解


以上是关于第九天(上) final和static关键字的主要内容,如果未能解决你的问题,请参考以下文章

javaSE第九天

final关键字的案例

No_16_0229 Java基础学习第九天

static关键字作用总结

学习java第九天个人总结

关键字this super final static