final关键字

final关键字
    1 final修饰的类无法继承。
    2 final修饰的方法无法覆盖。
    3 final修饰的变量只能赋值一次值。
    4 final修饰的引用一旦指向某个对象,则不能在重新指向其他对象,但该引用指向的对象内部的数据是可以修改的。
    5 final修饰的实例变量必须手动初始化,不能采用系统默认值。
    6 final修饰的实例变量一般和static联合使用,称为常量。
        public static final double PI = 3.1415926;
 
案例1:
/*
* final
*   1 final是java语言中的一个关键字。
*   2 final表示最终的,不可变得。
*   3 《重点》final修饰的变量?
*       final修饰的局部变量,一旦赋值,不能重新赋值。
*
*   4 《重点》final修饰的方法?
*       final修饰的方法无法被覆盖,被重写。
*
*   5 《重点》final修饰的类?
*       final修饰的类无法被继承
*
*   6 《提示》final控制不了能不能调用的问题。final管的是啥?
*       final修饰的表示最后的。不能变的,不能改的。
*
*   重点【精辟:final修饰的变量,只能赋一次值。】
* */
public class FinalTest01 {
    public static void main(String[] args) {
        D d = new D();
        d.doSome();

        // 局部变量
        int i =100;
        // 重新赋值
        i = 200;

        // 局部变量
        final int k = 100;
        // 重新赋值
        // Error:(28, 9) java: 无法为最终变量k分配值
        // k = 300;

        // 初始化这个m
        final int m;
        // 重新赋值
        m = 200;
        // 二次赋值
        // Error:(38, 9) java: 可能已分配变量m
        // m = 300;

    }
}

final class A{ // A没有子孙

}

// B类继承A类,相当于对A类的功能进行扩展。如果你不希望别人对A类型进行扩展。
// 你可以给A类加一个final关键字,这样的话A类就无法继承了。
// 错误:无法从最终A进行继承
/*class B extends A{

}*/

// Error:(26, 24) java: 无法从最终java.lang.String进行继承
/*class MyString extends String{

}*/
class C{
    public final void doSome(){
        System.out.println("C's doSome...");
    }
}

/*Error:(39, 17) java: D中的doSome()无法覆盖C中的doSome()
  被覆盖的方法为final*/
class D extends C{
    /*public void doSome(){
        System.out.println("D's doSome...");
    }*/
}

 

内存图:

 

 

 

案例2:

/*
* final修饰的变量,如果这个变量是一个“引用”会怎样???
* 《重点》final修饰的变量只能赋一次值。(万变不离其宗)
* “引用”是不是一个变量呢????是
*
* final修饰的引用:
*   该引用只能指向1个对象,并且他只能永远指向该对象。无法在指向其他对象。
*   并且在该方法在执行过程中,该引用指向该对象之后,该对象不会被垃圾回收器回收。
*   直到当前方法结束,才会释放空间。
*
*   虽然final的引用指向对象A后,不能在重新指向对象B
*   但是对象A内部的数据可以被修改。
* */
public class FinalTest02 {
    public static void main(String[] args) {
        Person person = new Person(30);
        System.out.println(person.age);


        //--------------------------------------


        // 代码不管怎么变化,p也是一个变量。(只不过这里他有一个特殊的名字:引用)
        final Person p = new Person(30);
        //Error:(9, 9) java: 无法为最终变量p分配值
        //p = new Person(30);
        //Error:(20, 9) java: 无法为最终变量p分配值
        //p = null;


        /*final int i = 10;
        // 这是不允许的
        i = 20;*/


        p.age = 40;
        System.out.println(p.age);
    }
}


class Person{
    int age;


    public Person() {
    }


    public Person(int age) {
        this.age = age;
    }
}

 

 

案例3:

/*
* final修饰的实例变量呢?
*   《重点:万变不离其宗》:final修饰的变量只能赋一次值。(这句话到哪里都好用)
*
* 你是否还记得:实例变量如果没有手动赋值的话,系统会默认赋值。
*
*  java程序设计:不背锅!!!甩锅甩的很好!!!
*
* 实例变量在什么时候赋值(初始化)?
*   构造方法执行的过程中赋值。(new的时候赋值)
*
* 终极结论:
*   final修饰的实例变量,系统不管赋默认值,要求程序员必须手动赋值。
*   这个手动赋值,在变量后面赋值可以,在构造方法中赋值也可以。
* */
public class FinalTest03 {
    public static void main(String[] args) {
        //创建对象必须调用无参构造方法吗?
        //不一定
        User user = new User(100);
        User user1 = new User(200);
    }
}


class User{
    // 实例变量
    // Error:(15, 15) java: 变量 age 未在默认构造器中初始化
    //final int age;


    // 实例变量
    int age;


    // 实例变量
    // 这样可以,因为程序员手动赋值了
    final double height = 1.8;




    // 以下这一堆代码全部联合起来,weigth变量也是赋值1次。
    // 实例变量
    final double weight;


    /*public User() {


        System.out.println("Hello World!");


        // 如果不这样写的话,那么系统在运行的时候会默认执行无参构造方法,那么他就赋默认值,这样是不行的。
        this.weight = 80;// 只要我赶在系统赋默认值之前赋值就行。


        // 如果你不写上面的代码,系统赋默认值是在这个时候
        // 那你给他赋默认值了,那就不可以进行修改了,那sun公司的java工程师不背锅,人家不允许你赋默认值。 所以就报错了。
        // weight = 0;


        //Error:(44, 13) java: 可能已分配变量weight
        //this.weight = 88;
    }*/


    // 这样跟上面是一样的
    public User(double weight) {
        // 这也是赋值了,没有采用系统默认值。他也是系统默认赋值一次。
        this.weight = weight;
    }
}

 

 

案例4:

/*
*
* 上一个例子的结论:
*   final修饰的实例变量,必须手动赋值。
*   《重点》final修饰的变量,只能赋一次值。
*
* final修饰的变量一般添加static进行修饰。
* 终极结论:
*   static final修饰的变量称为“常量”。
*   常量名建议全部大写。每个单词之间用下划线进行衔接
*
* 常量:实际上常量和静态变量一样,区别在于:
*   常量的值不能变。
*   常量和静态变量,都是存储在方法区,并且都是在类加载时初始化。
*
* 常量一般都是公共的:public的,因为你改不了。
* */
public class FinalTest04 {
    public static void main(String[] args) {
        System.out.println(Chinese.COUNTRY);


        //Error:(20, 16) java: 无法为最终变量COUNTRY分配值
        //Chinese.COUNTRY = "美国";


        System.out.println(MyMath.PI);
    }
}


class Chinese{
    // 身份证号 每个人都不一样 对象级别的
    String idCard;
    // 姓名,对象不同姓名不同。
    String name;
    // 国家的值是一个固定的值,中国
    // 实例变量在堆中,一个对象一份,一百个对象一百份。
    // 实例变量既然使用final修饰了,说明该实例变量值不会随着对象的变化而变化。
    // 该实例变量前面应该添加:static关键字,变为静态的,存储在方法区。
    // static final String country = "中国";
    static final String COUNTRY = "中国";


    // i永远都是10,创建100个对象,i也是10
    // i是10永远都不会发生改变的,既然这样,没必要声明为实例变量,最好是静态的,节省内存空间。
    static final int I = 10;
}


class MyMath{
    // 数学中的π是永远不会变的
    public static final double PI = 3.141592627;
}

 

posted @ 2020-06-10 22:30  xlwu丶lz  阅读(165)  评论(0编辑  收藏  举报