美文网首页
Java基础_final修饰符

Java基础_final修饰符

作者: dashingqi | 来源:发表于2020-03-15 19:27 被阅读0次

final修饰变量

  • final关键字可以修饰类、变量、方法。

final修饰符

  • final修饰的变量不可被改变,一旦获取了初始值,该final变量的值就不能被重新赋值。
  • final在修饰成员变量和修饰局部变量时有一定的不同。

final成员变量

针对final修饰的成员变量一旦有了初始值,就不可以改变了。

  • 类成员变量

    • 当类初始化的时候,系统会为类的变量分配内存,并分配默认值。�
    • 类的成员变量可以在声明的时候进行赋值,也可以在静态代码块中进行赋值。
  • 实例成员变量

    • 当创建实例的时候,会为实例的成员变量开辟内存空间,然后分配默认值。
    • 实例的成员变量可以在声明的时候指定默认值,也可以在构造器或者代码块中进行赋值。
    注意
    • 如果在代码块中进行了赋值,就不能在构造方法中进行赋值。不然是错误的代码。
    • 实例成员变量是不能在静态代码块中进行赋值,本身静态代码块是属于类的成员,不能去操作非静态成员。
  • 针对成员变量,没有通过任何途径进行赋初始值,那么系统将会默认分配默认值 0、false,null。

  • 然后这些变量就失去了存在的意义了。

  • 因为就规定,final修饰的成员变量必须由我们手动进行赋值。

与普通成员变量的对比
  • final修饰的成员变量必须手动赋初始值,系统不会对final成员进行隐式�初始化。

final局部变量

系统不会对局部变量进行初始化,局部变量必须由我们自己手动进行初始化。

所以局部变量可以在定义时赋值,也可以不指定默认值

指定默认值
  • 如果指定了默认值,在后面的代码中不能对该变量进行赋值操作
没有指定默认值
  • 如果没有指定默认值,可以在后面的代码中对final的变量赋初始值,有且只有一次。

final修饰基本类型变量和引用类型变量的区别

基本类型变量
  • 如果对基本类型的变量赋初始值了,后面就不能对其进行修改。
引用类型变量
  • 对于引用类型变量来说,它仅仅保存的是引用,
  • final修饰的话保证引用类型变量所引用的地址不变即可,也就是引用同一个对象。(也即是引用类型变量不能重新被赋值)
  • 但是这个对象可以完全发生改变。

可执行“宏替换”的final变量

直接变量
  • 针对类变量,实例变量还是局部变量,只要满足如下三个条件,就称之为直接变量
    • final修饰
    • 在定义final变量时指定了初始值
    • 该初始值可以在编译时就被确认下来。
重要用途之一
  • final修饰符的重要用途之一就是“宏变量”。当满足如上三个条件的时候,那么本质上就是一个宏变量。

  • 编译器会把程序中所有用到该变量的地方直接替换成该变量的值。

    public class FinalLocalTest{
      public static void main(String[] args){
        final int a = 9;
        System.out.println(a);
      }
    }
    // 上面这段代码,其实变量a根本不存在,当程序执行到打印语句的时候,实际是吧 a变量对应的值替换成了a
    
  • 除了赋直接量的情况下,赋的表达式只是基本算术表达式或者字符串连接运算,没有访问普通变量,调用方法,同样会将这种fina变量当成宏变量处理。

    public class Test {
    
        public static void main(String[] args) {
    
            final String name = "zhangqi";
            final String name1 = "zhang" + "qi";
              // name2 因为涉及到String中方法的调用,所以name2就不是宏变量
            final String name2 = "zhang" + new String("qi");
    
            // true
            System.out.println(name1 == "zhangqi");
            // false
            System.out.println(name2 == "zhangqi");
        }
    
    }
    
    加深印象
    • Java中会使用常量池来管理曾经使用过的字符串变量

    • 比如执行 String a = "abc"�后,会在常量池中缓存一个字符串的“abc”

    • 当程序再次出现 String b = "abc",此时会将b直接指向了常量池中的“abc”字符串

    • 因此 a == b true

      public class Test2 {
      
          public static void main(String[] args) {
              //把字符串dashignqi存储到常量池中
              String sta = "dashingqi";
              // (在编译阶段就可以确认str1)str1 直接指向常量池中dashingqi的字符串
              String str1 = "dashing" + "qi";
              // true
              System.out.println(sta == str1);
      
               String a = "dashing";
               String b = "qi";
              // 由于a,b是两个普通的变量,所以不会进行宏替换
              String c = a + b;
              // false
              System.out.println(c == sta);
              
              // 当把把a,b 使用final修饰的时候,就可以执行宏替换
              // 也就是 String c = "dashing"+"qi";
          }
      }
      

final方法

  • final修饰的方法是不能被子类重写的。

  • 在Object类中就有一个final方法:getClass();

    public class MyFinalMethod {
        public final void methodA() {
            System.out.println("super");
        }
    }
    
    public class MuSuberClass extends MyFinalMethod {
          // 当你试着重写父类中的 public final修饰的方法的时候,会编译报错的
        public final void methodA(){
    
        }
    }
    
针对private修饰的方法
  • 在父类中private修饰的方法子类是无法访问到的,所以子类无法重写该方法。
  • 但是在子类中可以新建一个和父类private修饰的方法同名,同返回值,同形参的方法,仅仅是子类中的一个新的方法与父类没有任何关系。

final类

  • 被final修饰的类不能被继承,也就是不能有子类。
  • 当子类通过继承,可以获取访问父类中某些数据,并且可重写某些方法
  • 这样可能导致一些安全因素。
  • 所以为了某个类不让继承,可以使用final去修饰。

不可变类

定义

  • 不可变类:当创建类的实例后,实例的变量是不可改变的。

  • Java中提供了8个包装类和String类都是不可变类,当它们创建实例的时候,实例的变量是不可变的。

    Double d = new Double(6.5);
    String str = new String("zhangqi");
    // 上述代码创建了Double对象和String对象,并且通过构造器传入了参数
    // 该参数在Double或者String类中,有相应的变量进行存储
    // 但是Double和String并没有提供修改该变量的方法
    // 这种的就叫做不可变类
    

创建自定不可变类的规则

  • 使用private和final修饰符来修饰该类的变量

  • 提供代参数构造器,用于根据传入参数来初始化类的变量。

  • 仅仅为该类的变量提供getter方法,不要提供setter方法。

  • 如果有必要,重写Object的hashCode和equals方法。

    • equals方法以关键变量作为判断两个对象是够相等的标准。

    • 还应该保证equals方法判断相等的两个对象hashCode也想等。

      public class ImmutableStringTest {
          public static void main(String[] args) {
              String str1 = new String("Hello");
              String str2 = new String("Hello");
              // false
              System.out.println(str1 == str2);
              // true
              System.out.println(str1.equals(str2));
              // 69609650====69609650 
              System.out.println(str1.hashCode() + "====" + str2.hashCode());
          }
      }
      
    自定义可变类
    • 代码如下,自定义一个不可变类Name

      public class Name {
          //1, private final修饰
          private final String name;
          private final String sex;
      
          public Name() {
              this.name = "";
              this.sex = "";
          }
      
      
          //2。 提供传入参数的构造器,赋给变量
          public Name(String name, String sex) {
              this.name = name;
              this.sex = sex;
          }
      
          // 3。仅仅提供getter方法,不提供setter方法去修改变量
          public String getName() {
              return name;
          }
      
          public String getSex() {
              return sex;
          }
      
          //重写 equals和hashCode方法
      
          @Override
          public boolean equals(Object obj) {
              if (this == obj) {
                  return true;
              }
              if (obj != null && obj.getClass() == Name.class) {
                  Name name = (Name) obj;
                  //当name和sex想等的时候,认为是想等的
                  if (this.getName().equals(name.getName()) && this.getSex().equals(name.getSex())) {
                      return true;
                  }
      
              }
              return false;
          }
      
          @Override
          public int hashCode() {
              return name.hashCode() + sex.hashCode() * 31;
          }
      }
      
      
    • 设置一个不可变类,需要注意引用类型变量,如果引用类型变量的类是可变的,就必须采取必要的措施来保护该变量所引用的对象不会被修改,这样才能创建真正的不可变类。

  • 与不可变类对应是可变类

    • 我们日常使用中创建的几乎都是可变类。特别是JavaBean,提供了getter和setter方法
    • 与可变类相比,不可变类的实例在整个程序的生命周期内都是处于初始化状态,不能进行任何修改。

final修饰符知识点总结

final修饰符.png

相关文章

  • java 面试题1

    一、JAVA基础 1、简述你所知道的JAVA修饰符及各自的使用机制?(public、abstract、final、...

  • Java中的final修饰符

    Java中的final修饰符 Java中final修饰符既可以修饰变量、方法,也可以修饰类。用final修饰的变量...

  • final修饰符

    final修饰符是java中比较简单的修饰符,但也是一个被误解最多的修饰符。final可以修饰变量,被final修...

  • Java基础_final修饰符

    final修饰变量 final关键字可以修饰类、变量、方法。 final修饰符 final修饰的变量不可被改变,一...

  • Android开发面试题

    1、JAVA中final、finally、finalize的区别 ① final:关键字,可以作为修饰符修饰变量、...

  • java代码开发注意事项

    1、尽量指定类的final修饰符 带有final修饰符的类是不可派生的。 在Java核心API中,有许多应用fin...

  • No.6final修饰符详解

    final作为java中的非访问修饰符可用于修饰类,接口,变量,方法; 被final修饰的类: final可以修饰...

  • Java 代码性能优化收录

    1、尽量指定类、方法的final修饰符带有final修饰符的类是不可派生的。在Java核心API中,有许多应用fi...

  • 牛客网学习笔记-day01

    Java修饰符大小 public>protected>default>private final方法不等同于pri...

  • final、finally、finalize的区别

    final、finally、finalize傻傻分不清楚,今天让你彻底弄清楚 基础概念区分 final 修饰符 将...

网友评论

      本文标题:Java基础_final修饰符

      本文链接:https://www.haomeiwen.com/subject/jzyuehtx.html