Java 中的 static 关键字
static 是 Java 的一个修饰符,用于修饰类的成员 (变量和方法)。它的核心思想是与类相关联,而不是与类的任何一个特定对象(实例)相关联。
一、静态变量(类变量)
-
定义 :被
static修饰的成员变量。 -
特点:
-
共享性 :被该类创建的所有对象所共享。在内存中只有一个副本。
-
类属性 :它不属于任何一个对象,而是属于定义它的类本身。
-
生命周期 :随着类的加载而加载到内存中的"静态区",优先于对象的创建而存在。直到程序结束才会被销毁。
-
-
调用方式:
-
类名.变量名(推荐,明确其静态属性) -
对象名.变量名(不推荐,容易混淆)
-
示例:
java
class Student {
String name;
// 静态变量:所有学生共享的学校名称
static String school = "第一中学";
public Student(String name) {
this.name = name;
}
}
public class Main {
public static void main(String[] args) {
Student s1 = new Student("小明");
Student s2 = new Student("小红");
System.out.println(s1.name + " 的学校是:" + Student.school); // 小明 的学校是:第一中学
System.out.println(s2.name + " 的学校是:" + Student.school); // 小红 的学校是:第一中学
// 通过类名修改静态变量,所有对象看到的都变了
Student.school = "实验中学";
System.out.println(s1.name + " 的学校现在是:" + Student.school); // 小明 的学校现在是:实验中学
}
}
二、静态方法(类方法)
-
定义 :被
static修饰的成员方法。 -
特点:
-
常用于工具类 和测试类。
-
在标准的
JavaBean类(主要用于描述事物的类,如Student,User)中较少使用。
-
-
调用方式:
-
类名.方法名()(推荐) -
对象名.方法名()(不推荐)
-
示例:
java
// 工具类示例:数学工具
class MathUtils {
// 私有构造方法,防止别人创建对象
private MathUtils() {}
// 静态方法,方便直接通过类名调用
public static int add(int a, int b) {
return a + b;
}
public static double circleArea(double radius) {
return Math.PI * radius * radius;
}
}
public class Main {
public static void main(String[] args) {
// 无需创建 MathUtils 对象,直接使用
int sum = MathUtils.add(5, 3);
double area = MathUtils.circleArea(2.5);
System.out.println("和: " + sum); // 和: 8
System.out.println("面积: " + area); // 面积: 19.634954...
}
}
三、工具类设计模式
这是静态方法的典型应用场景。
-
定义:一个只包含静态方法和静态变量的类,用于提供通用功能,而不描述任何具体事物。
-
设计规范:
-
类名见名知意 (如
Arrays,Collections,MathUtils,StringUtils)。 -
提供私有构造方法 (
private修饰构造器),防止外界通过new创建实例,强调其"工具"属性。 -
方法定义为静态的,方便通过类名直接调用。
-
四、static 的注意事项(重点)
这是理解 static 的关键,涉及访问权限 和 this 关键字。
| 方法类型 | 可以访问 | 不可以直接访问 | 原因解释 |
|---|---|---|---|
| 静态方法 | 静态成员(变量/方法) | 非静态成员(实例变量/方法) | 静态方法在类加载时就存在,此时可能还没有任何对象被创建。非静态成员属于对象,没有对象就无法访问。 |
| 非静态方法 | 所有成员(静态 + 非静态) | (无) | 非静态方法必须通过对象调用。当对象存在时,静态成员(属于类)和非静态成员(属于该对象)都已确定存在。 |
-
this关键字:-
this代表当前对象的引用。 -
因为静态方法可以通过
类名.方法名()调用,此时没有"当前对象"的概念,所以静态方法中不能使用this关键字。 -
非静态方法必须由对象调用,所以内部可以使用
this。
-
示例:
java
class Example {
int instanceVar = 10; // 实例变量(非静态)
static int staticVar = 20; // 静态变量
// 非静态方法
public void nonStaticMethod() {
System.out.println(instanceVar); // OK,访问自己的
System.out.println(staticVar); // OK,访问静态的
this.instanceVar = 30; // OK,this 存在
staticMethod(); // OK,调用静态的
}
// 静态方法
public static void staticMethod() {
// System.out.println(instanceVar); // 编译错误!不能访问非静态变量
System.out.println(staticVar); // OK,访问静态的
// this.staticVar = 40; // 编译错误!不能使用 this
// nonStaticMethod(); // 编译错误!不能调用非静态方法
}
}
总结
-
核心区分 :静态属于类,非静态属于对象。
-
访问规则 :静态方法只能访问静态成员。非静态方法可以访问所有。
-
this:静态方法中没有this。 -
设计思想:将与对象状态无关的、通用的功能设计为静态方法和工具类,提高代码的复用性和组织性。将与对象状态相关的行为设计为非静态方法。
java
package a01staticdemo1;
public class StudentText {
public static void main(String[] args) {
Student.teacherName = "YUQI";
//1.创建第一个学生对象
Student s1 = new Student();
s1.setName("张三");
s1.setAge(18);
s1.setGender('男');
//s1.teacherName = "yuqi";
s1.study();
s1.show();
//1.创建第二个学生对象
Student s2 = new Student();
s2.setName("李四");
s2.setAge(20);
s2.setGender('男');
s2.study();
s2.show();
}
}
package a01staticdemo1;
public class Student {
//属性:姓名 年龄 性别
private String name;
private int age;
private char gender;
//新增:老师的姓名
public static String teacherName;
public Student(String name, int age, char gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public void study(){
System.out.println(name+"正在学习");
}
public void show(){
System.out.println(name+", "+age+", "+gender+", "+teacherName);
}
}
java
package a02staticdemo2;
public class TextDemo {
public static void main(String[] args) {
int[] arr1 = {1,2,3,4,5,6};
String str = ArrayUtil.printArr(arr1);
System.out.println(str);
double[] arr2 = {4.5,3.5,9.6,7.2};
double avg = ArrayUtil.getAverage(arr2);
System.out.println(avg);
}
}
package a02staticdemo2;
public class ArrayUtil {
//私有化构造方法
//目的:为了不让外界创建他的对象
private ArrayUtil(){
}
//需要定义为静态方便调用
public static String printArr(int[] arr){
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length-1){
sb.append(arr[i]).append("] ");
}else {
sb.append(arr[i]).append(", ");
}
}
return sb.toString();
}
public static double getAverage(double[] arr){
double sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum/ arr.length;
}
}
java
package a03staticdemo3;
import java.util.ArrayList;
public class TextDemo {
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<>();
Student s1 = new Student("zhangsan",23,"nan");
Student s2 = new Student("lisi",24,"nv");
Student s3 = new Student("wangwu",25,"nan");
list.add(s1);
list.add(s2);
list.add(s3);
int max = StudentUtil.getMaxAgeStudent(list);
System.out.println(max);
}
}
package a03staticdemo3;
import java.util.ArrayList;
public class StudentUtil {
private StudentUtil(){}
public static int getMaxAgeStudent(ArrayList<Student> list){
int max = list.get(0).getAge();
for (int i = 1; i < list.size(); i++) {
int tempAge = list.get(i).getAge();
if ((tempAge > max)){
max = list.get(i).getAge();
}
}
return max;
}
}
package a03staticdemo3;
public class Student {
private String name;
private int age;
private String gender;
public Student() {
}
public Student(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}