面向对象通识16(final变量)

面向对象通识16(final修饰符)

final可以修饰变量(各种变量)、方法、类

finalabstract是互斥的,无法同时出现。

特性

final修饰类

该类不能再派生子类(与abstract互斥的主要原因)

final修饰类变量

  • 该变量被赋初始值之后,不能被重新赋值。
  • 该变量必须被赋值

final修饰成员变量

  • 对于普通的成员变量,可以不显示指定的初始值,系统会位置分配默认的初始值。

(该初始值分配规则与数组元素的初始值分配规则完全相同)

  • 对于final修饰的成员变量,程序员必须分配指定的初始值

    • final实例变量,必须显示指定的初始值。只能在以下3个位置的其中之一指定:

      • 定义时指定初始值

      • 实例初始化块

      • 构造器

        上面三个位置本质上都是要还原到构造器

        不能在普通方法中赋值!

        public class Final实例变量 {
            final int age=20;
            final String s="java";;
            final long lg;
            {
                lg=2333333;
            }
            public void sc(){
            }
        }
        
    • final修饰的类变量,必须显示指定的初始值。只能在以下2个位置的其中之一指定:

      • 定义时指定初始值

      • 类初始化快

        本质上都是在类初始化快中指定初始值

        实例初始化快可以访问final类变量,但不能指定初始值

        public class Final类变量 {
            static final int a=10;
            static final String m;
            static {
                m="z";
            }
            void a(){
                System.out.println(m);
            }
        }
        
  • 对于非final修饰的局部变量,程序员必须指定初始值,然后才能使用

  • 对于final修饰的局部变量,程序员必须指定初始值,然后才能使用,与前者唯一的区别就是不能被重新赋值

  • 如果final修饰的是引用类型的变量——

    final只能保证该引用变量本身不会被重新赋值,该变量所引用的对象完全可以被修改

public class Final引用类型 {
    public static void main(String[] args) {
        final Pig p=new Pig("white",4);
        //只能保证p不能被重新赋值
        p.setColor("black");
        p.setWeight(5);
        System.out.println(p.getColor());
        System.out.println(p.getWeight());
    }

}
class Pig{
    private String color;
    private int weight;

    public Pig(String white, int i) {

    }

    public void setColor(String color){
        this.color=color;
    }
    public void setWeight(int weight){
        this.weight=weight;
    }
    public String getColor(){
        return this.color;
    }
    public int getWeight(){
        return this.weight;
    }
}

final修饰宏替换的变量

条件

  • 变量有final修饰
  • 声明变量时指定初始值
  • 变量的初始值可以在编译的时候确定下来(初始值的表达式中没有变量、方法调用等)

这个变量就会消失,所有出现该变量的地方,在编译的时候就会出现该变量的值

public class 宏变量 {
    public static void main(String[] args) {
        final int MAX=100;
        //有final修饰,指定了初始值,并且初始值在编译的时候就可以确定
    }
}

举例:

public class 宏变量 {
    public static void main(String[] args) {
        String a="a";
        String b="a";
        System.out.println(a==b);
        String s1="accd";
        String s2="ac"+"cd";//编译阶段就会计算结果
        System.out.println(s1==s2);
        String s3="ac";
        String s4="cd";
        String c=s3+s4;//s3和s4是变量,在运行的时候才会计算
        System.out.println(c==s1);
        final String s7="ac";
        final String s8="cd";
        String d=s7+s8;//s7和s8有final修饰并在声明的时候已经指定了初始值,出现了宏替换
        System.out.println(d==s1);
    }
}
/*
true
true
false
true
*/

例题2

public class 例题 {
    public static void main(String[] args) {
        final String s1="wyd";
        final String s2=s1+" is";
        final String s3=s2+" unjuanable";
        System.out.println(s3);
    }
}
/*
wyd is unjuanable
*/

上述代码经过了3次宏替换

final修饰方法

final修饰的方法可以被重载,可以被子类调用,但不能被重写(避免该方法被子类破坏)

举例1

class A{
    public final void info(){
        System.out.println("info");
    }
}
public class 调用方法 extends A {
    @Override
    public void info(){
        System.out.println("change");
    }
}
/*
'info()' cannot override 'info()' in 'Final宏变量.A'; overridden method is final
*/

举例2

class Foo {
    //private方法已经隐藏在该类的内部不可能被重写,子类无法访问
    private final void test(){
        System.out.println("2333");
    }
}
public class F1 extends Foo{
    public void test()
    {
        System.out.println("32222");
    }

    public static void main(String[] args) {
        F1 a=new F1();
        a.test();
    }
}
/*
32222
*/

在例2中 private方法已经隐藏在该类的内部不可能被重写,子类无法访问,

逻辑上final在这里是多余的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值