静态(static)
概述
- static关键字是静态的意思,可以修饰成员方法,成员变量
- jdk8之后静态变量保存在堆内class对象的尾部
- jdk8之前存放在方法区静态域中(都不影响使用)
static的特点
- 被类的所有对象共享
- 判断是否使用静态关键字的条件
- 可以通过类名调用(推荐),也可通过对象调用
访问特点
- 非静态成员方法
- 能访问静态跟非静态的成员变量
- 能访问静态跟非静态的成员方法
- 静态成员方法
- 能访问静态的成员变量以及方法
- [静态方法只能访问静态成员]
注意事项
- 静态变量(类变量)
- 当需要让某个类的所有对象共享一个类时,可以考虑使用静态变量
- 静态变量是该类所有对象共享的,而实例变量是每个对象独享的
静态方法(类方法)
- 当方法不涉及到任何和对象相关的成员,则可以将方法设置为静态方法,提高开发效果
- 静态方法无this的参数 普通方法隐含this的参数(静态方法不能使用this super关键字)
静态方法中只能访问静态变量或静态方法 :::
public static void main(String[] args) {
//类名.类变量名 推荐
//类变量随着类的加载而创建,所以没有创建对象实例也可以访问
System.out.println(A.name);
//对象名.类变量名
A a = new A();
System.out.println(a.name);
}
}
class A {
public static String name = "静态变量";
}
public static void main(String[] args) { Stu stu1 = new Stu("张三"); //方法名.静态方法名调用 stu1.payFee(100.0); Stu stu2 = new Stu("张三"); //类名.静态方法名调用 Stu.payFee(200.0); Stu.showFee(); } class Stu { private static double fee = 0; private String name; //无参带参构造方法 //当方法使用static修饰后,该方法为静态方法 //静态方法就可以访问静态变量 public static void payFee(double fee) { Stu.fee += fee; } public static void showFee() { System.out.println("总学费:" + Stu.fee); } }
状态修饰符:final(最终态)
final(最终态)
final关键字是最终的意思,可以修饰成员方法,成员变量,类
final修饰的特点:
- 修饰类:表明该类是最终类,不能被继承
- 修饰方法:表明该方法是最终方法,不能被重写
- 修饰变量:表明该变量是常量,不能再次被赋值
final修饰局部变量
- 变量是基本类型:final修饰指的是基本类型的数据值不能发生改变
- 变量是引用类型:final修饰指的是引用类型的地址值不能改变,但是地址值里的内容可以改变
注意事项
- final修饰的属性又叫常量
- final修饰属性在定义时必须赋值,并且不能修改
- final不能赋值但可实例化对象
- 如果不是final类但有final方法,则该方法不能重写但可以继承
- 如果一个类为final类则方法没必要修饰为final方法
- final不能修饰构造方法(构造器)
- final跟static搭配使用效率更高,底层编译器做了优化处理
final修饰成员变量时必须先赋值或者在构造方法中赋值 :::
代码块
概述:
相当于另一种格式的构造器(对构造器的补充机制)可以初始化的操作
- 如果多个构造器有相同的语句,可以初始化到代码块中,提高代码重用性
注意事项
- static代码块的作用是对类进行初始化,而且伴随类加载而执行,并且执行一次
如果是普通代码块,每创建一次变量就执行一次
- 类什么时候被加载
- 第一次创建对象实例时(new)
- 创建子类对象实例,父类也会被加载(父类先被加载)
- 使用类的静态成员时(静态属性静态方法)
- 在类中运行main方法时
- 普通代码块在创建对象实例时,会被隐式调用,创建一次就调用一次,如果使用类的静态成员时普通代码并不会执行
#▲创建一个对象时,在一个类中的调用顺序:
- 调用静态代码块和静态属性的初始化(优先级相同,按顺序调用)
- 调用普通代码块和普通属性的初始化(优先级相同,按顺序调用)
-
#▲创建一个子类对象时(继承关系),调用顺序:
父类静态代码块和静态属性(优先级相同,按顺序调用)
- 子类静态代码块和静态属性(优先级相同,按顺序调用)
- 父类普通代码块和普通属性初始化(优先级相同,按顺序调用)
- 父类构造方法
- 子类普通代码块和普通属性初始化(优先级相同,按顺序调用)
- 子类构造方法
静态代码块只能直接调用静态属性和静态方法,普通代码块可以调用任意成员
::: ```java public static void main(String[] args) { Movie movie = new Movie(“你好,李焕英”); /*运行结果:
}广告 好戏开场 调用一个参数*/
class Movie { private String name; private double price;
//不管调用哪个构造器 代码块优先调用
{
System.out.println("广告");
System.out.println("好戏开场");
}
public Movie() {
System.out.println("调用无参");
}
public Movie(String name) {
System.out.println("调用一个参数");
this.name = name;
}
public Movie(String name, double price) {
System.out.println("调用满参");
this.name = name;
this.price = price;
}
}
```java
public static void main(String[] args) {
//创建对象实例时(new)
//new AA();
//创建子类对象实例 父类也会被加载 (先调用父类)
//new BB();
//使用类的静态成员时(静态属性静态方法)
int cat = CC.cat;
}
class AA {
static {
System.out.println("AA的静态代码被执行");
}
}
class BB extends AA {
static {
System.out.println("BB的静态代码被执行");
}
}
class CC {
public static int cat = 0;
static {
System.out.println("CC的静态代码被执行");
}
}
单例设计模式(饿汉式·懒汉式)
区别:
- 两者区别于创建对象的时机不同,饿汉式是类加载就创建,懒汉式是使用才创建
- 饿汉式不存在线程安全问题,懒汉式存在线程安全问题
饿汉式存在浪费资源可能,懒汉式使用才创建所以不存在这个问题 :::
public static void main(String[] args) { GirlFriend girlFriend = GirlFriend.getInstance(); System.out.println(girlFriend); } /* 饿汉式单例设计模式 1.构造器私有化 2.类的内部创建对象 3.向外暴露一个静态修饰方法 [饿汉式可能创建了对象但没有用] */ //只能有一个对象 class GirlFriend{ private GirlFriend() {} private static GirlFriend gF = new GirlFriend(); public static GirlFriend getInstance() { return gF; } }
public static void main(String[] args) { Cat instance = Cat.getInstance(); System.out.println(instance); } /* 懒汉式单例设计模式 1.构造器私有化 2.创建一个static静态属性对象 3.提供一个公共的public的static方法,可以返回cat对象 4.只有使用getInstance()时,才会返回cat对象, 再次调用时会返回上次创建的cat [饿汉式可能创建了对象但没有用] */ //只能创建一个对象 class Cat { private static Cat cat; private Cat(String name) {} public static Cat getInstance() { if (cat == null) { cat = new Cat(); } return cat; } }