Static
static 的中文意思是"静态",它可以修饰成员变量、成员方法
1. Static 修饰成员变量
- static 修饰的成员变量,也称之为"类变量"
- 类变量它是属于类的,与类一起加载,在内存中只有一份,会被类的所有对象共享
- 无 static 修饰的成员变量,称之为 " 实例变量 (对象变量) "
- 实例变量 (对象变量) 是属于对象的,每个对象中都有一份
public class HelloWorld {
public static void main(String[] args) {
Human.name = "人类"; // 直接通过 "类名.类变量名" 的方式来访问(推荐此方法)
Human obj = new Human();
obj.name = "人才"; // 也可以通过 "对象.类变量名" 的方式访问,但是不推荐此方法!
}
}
class Human {
// 类变量
static String name;
// 实例变量(对象的变量)
int age;
}
2. 类变量的使用场景
在开发中,如果某个数据只需要一份,且希望能够被共享 (访问、修改),则该数据可以定义成类变量来记住。
import java.util.ArrayList;
public class HelloWorld {
public static void main(String[] args) {
// 创建一个集合,用来存放对象
ArrayList list = new ArrayList();
System.out.println(Human.number); // 0
for (int i = 0; i < 5; i++) {
Human obj = new Human();
list.add(obj);
}
System.out.println(Human.number); // 5
}
}
class Human {
// 类变量
static int number; // 没必要自己手动初始化,因为默认自动初始化为 0
public Human() {
Human.number++;
// 在同一个类中,访问自己类的类变量,可以省略不写前面的 Human
// 即:可以将 Human.number++ 写成 number++
}
}
3. static 修饰成员方法
- 类方法:有 static 修饰的成员方法,属于类
- 实例方法:无 static 修饰的方法,属于对象
public class HelloWorld {
public static void main(String[] args) {
Human.printHelloWorld(); // 直接通过"类名.类方法名"进行调用(推荐使用此方法)
Human obj = new Human();
obj.printHelloWorld(); // 不推荐使用此方法
obj.printGood();
}
}
class Human {
// 类方法
public static void printHelloWorld() {
System.out.println("Hello World");
}
// 实例方法(对象的方法)
public void printGood() {
System.out.println("Good");
}
}
4. 类方法的使用场景
-
类方法最常见的应用常见是做工具类
-
什么是工具类?
简单的说,就是创建一个类,在里面写一些功能,方便别人去调用你写的工具;
而在工具类中,使用的方法都是一些类方法,而不是实例方法
因此,工具类没有创建对象的需求,建议将工具类的构造器进行私有,从而禁止他人创建对象
另外要注意的是,一般情况下,每个方法都是用来完成一个功能的。
-
为什么工具类中的方法要使用类方法,而不用实例方法?
首先,实例方法确实也能够实现做工具类,但是!实例方法需要创建对象来调用,而如果大费周章创建了一个对象,却只是为了用它来调用实例方法,在操作上看,这是多此一举,在内存上看,它还浪费了内存。
-
使用类方法设计工具类的好处
提高了代码的复用;调用方便,提高了开发效率。
5. 代码块
概述:代码块是类的5大成分之一(成员变量、方法、构造器、代码块、内部类)
代码块分两种
-
静态代码块:static { }
特点:类加载时自动执行,由于类只会加载一次,所以静态代码块也只会执行一次
作用:完成类的初始化,例如:对类变量的初始化赋值
-
实例代码块:{ }
特定:每次创建对象时,都会先执行实例代码块,再执行构造器
作用:和构造器一样,都是用来完成对象的初始化操作的,例如:对实例变量进行初始化赋值
public class HelloWorld {
public static void main(String[] args) {
// 先加载一次类,执行一次 static{},再同步执行 Human.number
System.out.println(Human.number);
System.out.println(Human.number);
System.out.println(Human.number);
// 实例代码块——功能演示
Human obj = new Human();
Human obj2 = new Human(25);
// 程序运行结果:
/*
静态代码块执行了~~
1
1
1
警告!有人创建了对象!对象内存地址: login.Human@682a0b20
此人使用了[无参]构造器创建对象
警告!有人创建了对象!对象内存地址: login.Human@3d075dc0
此人使用了[含参]构造器创建对象
*/
}
}
class Human {
static int number;
// 静态代码块
static {
System.out.println("静态代码块执行了~~");
number++;
}
// 实例代码块
{
System.out.println("警告!有人创建了对象!对象内存地址: " + this);
}
public Human() {
System.out.println("此人使用了[无参]构造器创建对象");
}
public Human(int age) {
System.out.println("此人使用了[含参]构造器创建对象");
}
}
6. 单例设计模式
什么是设计模式?
- 一个问题通常有n种解法,其中肯定是有一种最优解法,这种解法被人总结出来了,称之为设计模式
- 设计模式有20多种,对应20多种软件开发中会遇到的问题
单例设计模式
- 要求:确保一个类只有一个对象
- 饿汉式单例:拿对象时,对象早就创建好了
- 懒汉式单例:拿对象时,才开始创建对象
- …
// 饿汉式单例
public class HelloWorld {
public static void main(String[] args) {
Human obj1 = Human.getObj();
Human obj2 = Human.getObj();
System.out.println(obj1 == obj2); // true
}
}
class Human {
private static Human obj = new Human(); // 此行代码只会在类加载时,执行一次
private Human() {
}
public static Human getObj() {
return obj;
}
}
// 懒汉式单例
public class HelloWorld {
public static void main(String[] args) {
Human obj1 = Human.getObj();
Human obj2 = Human.getObj();
System.out.println(obj1 == obj2); // true
}
}
class Human {
private static Human obj;
private Human() {
}
public static Human getObj() {
if (Human.obj == null) {
obj = new Human();
}
return obj;
}
}