目录

final关键字

了解到final关键字是学习String类的时候,表示String类是不可变的。

final的基本用法

在Java中,final关键字可以修饰方法变量(包括成员变量和局部变量)

1.修饰类

  • 当用final修饰一个类的时候,表示这个类不可以被继承,final修饰的类,所有的成员方法都被隐式的指定为final方法,要谨慎使用final修饰类,防止以后继承的时候,出现问题

2.修饰方法

  • 方法锁定,也就是这个方法的的具体任务被确定了,防止继承类修改这个方法的含义
  • 提高效率,早期的Java实现版本中,会将final指定的方法内嵌调用,但是如果方法过于庞大,这种方式效率方面就没什么体现了,所以后期的JDK中,不需要使用final修饰方法优化了
  • 类的private方法会隐式的指定为final方法

3.修饰变量

  • 这种用的较多,对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象(比如String变量)

深入理解final关键字

1.final变量和普通变量的区别

  • 当final作用于类的成员变量时(因为局部变量只需要在使用前被初始化赋值即可),成员变量必须在定义或者构造器中被初始化赋值,一旦被赋值,就不可以再更改了。
public class Demo1_final {
    public static void main(String[] args) {
        String a = "helloworld";
        final String b = "hello";
        String c = "hello";
        String d = b + "world";
        String e = c + "world";
        System.out.println(a == d); //true
        System.out.println(a == e); //false
    }
}

区别就是final作用的变量是基本数据类型或String类型时,如果在编译期间就能知道他的确切值, 则编译器就会把它当编译器常量使用,也就是说用到final变量时,直接使用final变量的值(涉及到JVM优化,d的值会在编译器直接去常量池取,也就是a的值),而不需要在运行时。对于d的访问却需要运行时通过链接进行

2.被final修饰的引用变量指向的对象内容可变吗?

  • 如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象,对象内容是可变的
    public class Demo2_final {
    
        public static void main(String[] args) {
            final Num num = new Num();
            System.out.println(++num.i);    //输出i为1,说明final修饰引用变量,不能指向别的对象,但指向对象的内容是可以修改的 
        }
    }
    class Num{
        public int i = 0;
    }
    

static关键字

特点

  • 一个类的多个对象共享,节省资源空间
  • 随着类的加载而加载
  • 可以通过类名调用

static的基本用法

在Java中,static的使用场景常常是直接使用类名调用,不用创建对象,static可以修饰类的成员方法类的成员变量,还可以编写static代码块来优化程序性能

1.static方法

  • 一般被成为静态方法,不需要任何对象就可以调用,因此对于静态方法是没有this的,由于这个特性,不能在静态方法中访问类的非静态变量和非静态成员方法,因为非静态方法/变量依赖对象才能调用,但是非静态方法中可以调用静态成员方法/变量,因为非静态方法的使用必须要创建对象来调用。
  • Java程序的主方法是static的也好理解了,我们运行程序的时候,不创建对象,main方法就要执行。

2.static变量

  • static变量也称静态变量,静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载的时候被初始化,而非静态变量是对象拥有的,创建对象的时候被初始化,存在多个副本,各个对象的副本互不影响

3.static代码块
使用static形成静态代码块,来优化性能,可以放在任何位置,类中可以有多个代码块,在类初次被加载的时候,会按照static块的顺序被执行,且只执行一次

class Person{
    private Date birthDate;
    private static Date startDate,endDate;
    static{     //使用静态代码块一次运行,可以一直使用,不用每次调用isBornBoomer()判断出生年份的时候,都创建两个对象
        startDate = Date.valueOf("1946"); 
        endDate = Date.valueOf("1964");
    }
     
    public Person(Date birthDate) {
        this.birthDate = birthDate;
    }
     
    boolean isBornBoomer() {
        return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;
    }
}

深入理解static关键字

1.static会改变类中访问权限吗
答案是不会的,能改变访问权限的只有private,public,protected等几个关键字

public class Demo3_static {
    public static void main(String[] args) {
        System.out.println(Person.age);   //'age' has private access ,意思就是age是私有的,不可视
        System.out.println(Person.name);

    }
}
class Person{
    public static String name = "cfl";
    private static int age = 24;   //使用了private,而并非是static的问题
}

2.static能作用于局部变量吗

Java中规定,不能使用static修饰局部变量

3.静态变量和成员变量的区别

  • 所属不同

    • 静态变量属于类,所以也叫类变量
    • 成员变量属于对象,也叫对象变量或实例变量
  • 内存中位置不同

    • 静态变量存储于方法区的静态区
    • 成员变量存储于堆内存
  • 内存中出现的时间不同

    • 静态变量随着类的加载而加载,随着类的消失而消失
    • 成员变量随着对象的创建而存在,随着对象的消失而消失
  • 调用不同

    • 静态变量可以通过类名调用,也可以通过对象调用
    • 成员变量必须由对象调用

this关键字

  • 初识this关键字是构造方法中,this.name=name
  • this关键字的使用环境主要有三种
    • 调用本类的中的属性或方法,也就是类的成员变量/成员方法
    • 调用本类的其他构造方法,调用时要放在构造方法的首行
    • 返回对象的值
      1.调用成员变量
public class Demo4_this {
    private String name;
    public void setName(String name) {
        this.name = name;
    }
}

上面代码中,this这个关键字其代表的就是对象中的成员变量,后面的name代表的是形参,this.name=name,表示的就是形参传给类的成员变量,也叫对象的属性

2.调用类的构造方法

public class Student {
    public Student() {
        this("helloWorld"); //调用哪个构造方法是根据参数确定的
    }
    public Student(String name) {   //创建一个带形参的构造方法

    }
}

在构造方法中,使用this关键字表示调用类中的构造方法,如果一个类中有多个构造方法,跟普通方法引用构造方法一样,都是通过形参来调用构造方法的
值得注意的是,使用this关键字调用构造方法,只能在无参构造方法的第一句使用this关键字,不然,Java编译的时候,可能会出现编译错误

3.返回对象的值

  • this关键字还有个作用就是返回类的引用。如在代码中,可以使用return this,来返回某个类的引用。此时这个this关键字就代表类的名称。如代码在上面student类中,那么代码代表的含义就是return student

super关键字

  • super关键字主要存在于继承关系的子类当中,用于在子类中指向父类对象
  • 可以访问父类的属性,方法和构造方法

1.子类的构造函数默认第一行会隐式调用父类的无参构造函数

public class Father {
    public Father() {  //父类的无参构造方法,不写的话,编译时会默认一个无参的空构造方法
        System.out.println("父类的构造方法");
    }
}
public class Son extends Father {

    public Son() {
        //super(); 隐式调用父类的无参构造方法,而且会优先调用父类的构造方法
        System.out.println("子类的构造方法");
    }

    public static void main(String[] args) {
        new Son();
    }
}
//输出为
父类的构造方法
子类的构造方法

2.子类调用父类的方法,和父类的属性值

public class Father {
    public int num;    //定义一个num成员变量
    public void test() {
       num=100;
    }
}

public class Son extends Father {

    public int num;
    public void test() {
        super.test();   //子类中调用父类的方法
        num = 200;
        System.out.println("子类中的num值:"+num);
        System.out.println("父类中的num值:"+super.num);  //子类中调用父类的属性值
    }
    public static void main(String[] args) {
        Son son = new Son();
        son.test();
    }
}
//输出为
子类中的num值:200
父类中的num值:100

3.如果开发者自定义了一个类,没有显示的进行类的继承,那么该类中成员函数是否可以使用super关键字?
可以使用,因为所有的类都是Object类的子类