static关键字
static是静态的意思,可以用来修饰成员变量、成员方法:
修饰成员变量
我们称为类变量,或静态变量,(类变量:属于类、加载一次,内存中只有一份)可以被类的所有对象共享(访问、修改)。
public class Test {
//类变量
public static String nationality = "中国";
public static void main(String[] args) {
//推荐使用类名访问
System.out.println("Test.nationality = " + Test.nationality); //Test.nationality = 中国
}
}
访问格式
实例成员变量(无static修饰的成员变量,属于对象),只能通过对象访问。访问格式:对象.实例成员变量
两种成员变量各自在什么情况下定义?
- 静态成员变量:表示在线人数等需要被类的所有对象共享的信息时。
- 实例成员变量:属于每个对象,且每个对象的该信息不同时(如:name,age,money…)
修饰成员方法
修饰方法之后称为静态方法(类方法)。静态成员方法(有static修饰的方法,归属于类),建议用类名访问,也可以用对象访问。
public class Demo {
public static void main(String[] args) {
//建议用类名访问,也可以用对象访问。
Demo.showInfo(); //静态方法
}
public static void showInfo(){
System.out.println("静态方法");
}
}
类方法访问格式:
实例成员方法(无static修饰,属于对象)的访问格式: 对象.实例成员方法
每种成员方法的使用场景是怎么样的?
- 表示对象自己的行为的,且方法中需要直接访问实例成员,则该方法必须申明成实例方法。
- 如果该方法是以执行一个通用功能为目的,或者需要方便访问,则可以申明成静态方法
注意事项:
- 静态方法只能访问静态的成员,不可以直接访问实例成员
- 实例方法可以访问静态的成员,也可以访问实例成员。
- 静态方法中是不可以出现this关键字的。
- 父类的静态方法可以被继承不能被重写
- 父接口的静态方法不能被实现类继承
static应用之一:工具类
工具类是什么?
- 类中都是一些静态方法,每个方法都是以完成一个共用的功能为目的,这个类用来给系统开发人员共同使用的。使用工具类的好处:调用方便丶代码复用
为什么工具类中的方法不用实例方法做?
- 实例方法需要创建对象调用丶每次调用都要创建对象会浪费内存
注意事项:
由于工具里面都是静态方法,直接用类名即可访问,因此,工具类无需创建对象,建议将工具类的构造器进行私有。
代码示例
/*
需求:
请在ArraysUtils中提供一个工具类方法toString,用于返回整数数组的内容,
返回的字符串格式如:[10, 20, 50, 34, 100](只考虑整数数组,且只考虑一维数组)
*/
public class MyUtil {
/**
* 注意:由于工具类无需创建对象,所以把其构造器私有化会显得很专业!
*/
private MyUtil() {
}
public static String toString(int[] arr) {
/*
*一些判断,提高健壮性
*/
if (arr == null) {
return null;
}
/*
* 实现功能
*/
String result = "[";
for (int i = 0; i < arr.length; i++) {
result += arr.length - 1 == i ? arr[i] : arr[i] + ", ";
}
result += "]";
return result;
}
}
定义测试类
public class Test {
public static void main(String[] args) {
int[] arr= {1,2,3,4};
//正常数组
System.out.println( MyUtil.toString(arr)); //[1, 2, 3, 4]
//数组内存地址为null
arr=null;
System.out.println( MyUtil.toString(arr));//null
//数组中没有元素存在
arr=new int[0];
System.out.println(MyUtil.toString(arr));//[]
}
}
static应用之一:单例设计模式
使用饿汉单例实现单例类
/**
使用饿汉单例实现单例类
*/
public class SingleInstance {
/**
2、饿汉单例是在获取对象前,对象已经提前准备好了一个。
这个对象只能是一个,所以定义静态成员变量记住。
*/
public static SingleInstance instance = new SingleInstance();
/**
1、必须把构造器私有化。
*/
private SingleInstance(){
}
}
懒汉单例
/**
懒汉单例
*/
public class SingleInstance2 {
/**
2、定义一个静态的成员变量负责存储一个对象。
只加载一次,只有一份。
注意:最好私有化,这样可以避免给别人挖坑!
*/
private static SingleInstance2 instance;
/**
3、提供一个方法,对外返回单例对象。
*/
public static SingleInstance2 getInstance() {
if(instance == null){
// 第一次来拿对象 :此时需要创建对象。
instance = new SingleInstance2();
}
return instance;
}
/**
1、私有化构造器
*/
private SingleInstance2(){
}
}
代码块
概述:代码块是类的5大成分之一(成员变量、构造器,方法,代码块,内部类),定义在类中方法外。 在Java类下,使用 { } 括起来的代码被称为代码块 。
代码块分类
静态代码块:
格式:
- 特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发、只执行一次
- 使用场景:在类加载的时候做一些静态数据初始化的操作,以便后续使用。
代码示例
/*
静态代码块:用于给静态变量进行赋值
静态代码块只会创建一次 再次创建n个对象 也不会再执行
先于构造器执行
执行顺序 按照从上到下执行
*/
import java.util.ArrayList;
//需求:在启动游戏房间的时候,应该提前准备好54张牌,后续才可以直接使用这些牌数据。
public class Test {
//定义一个静态的ArrayList集合存储54张牌对象,静态的集合只会加载一份。
public static ArrayList<String> arrayList;
static {
arrayList = new ArrayList<>();
// a、定义一个数组存储全部点数:类型确定了,个数确定了。
String[] sizes = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
// b、定义一个数组存储全部的花色:类型确定了,个数确定了。
String[] colors = {"♥", "♠", "♦", "♣"};
for (int i = 0; i < sizes.length; i++) {
for (int j = 0; j < colors.length; j++) {
String s = sizes[i] + colors[j];
arrayList.add(s);
}
}
arrayList.add("大王");
arrayList.add("小王");
}
public static void main(String[] args) {
System.out.println(arrayList);
}
}
构造代码块
- 格式:
- 特点:每次创建对象,调用构造器执行时,都会执行该代码块中的代码,并且在构造器执行前执行
- 使用场景:初始化实例资源。
private String name;
/**
实例代码块:无static修饰,属于对象,每次构建对象时,都会触发一次执行。
初始化实例资源。
*/
{
name = "张三";
}
native关键字
- 作用:只能修饰方法,表示这个方法的方法体代码不是用Java语言实现的,而是由C/C++语言编写的。但是对于Java程序员来说,可以当做Java的方法一样去正常调用它,或者子类重写它。
JVM内存的管理:
详解: