基本概念一句话来概括:方便在没有创建对象的情况下来进行调用。
也就是说:被static关键字修饰的不需要创建对象去调用,直接根据类名就可以去访问。
首先我们来看这个图,当我们想创建同班同学的几个学生对象时,对学生类的变量姓名、年龄、学号,按理每个对象都要有自己独立的数据。但是对于所在较是来说,这应该时多个对象共享同一份数据才对。不如将这个共享数据就放在类里(只在类当中保存唯一一份,那所有本类对象共享同一份),这就引出我们学习static关键字。
一旦用了static关键字,那么这样的内容不再属于对象自己,而是属于类的,所以凡是本类的对象,都共享同一份。
1.当static修饰成员变量时,可以先不在类里对其赋值,创建多个对象后,有一个给它赋值了,其他对象都共享这个成员变量值。
回忆知识点:Java三大特性之一就是封装,可以用方法封装,也可以用关键字private封装,对于一些不可信对象进行的不合理数据设置,private可以将该成员保护起来,对不可信对象隐藏信息。
public class Student { private int id; private String name; private int age; static String room; private static int idCounter = 0; // 学号计数器 public Student() { this.id = ++idCounter; // 每当new了一个新对象的时候,计数器++ } public Student(String name, int age) { this.name = name; this.age = age; this.id = ++idCounter; } public int getId() { return id; } public void setId(int id) { this.id = id; } 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 static void main(String[] args) { // 有参构造方法创建对象的时候,学号++ Student one = new Student("郭靖", 19); one.room = "1班"; // 此时只给郭靖赋值了班级 Student two = new Student("黄蓉", 16); // 但都输出了教室1班 System.out.println("姓名:" + one.getName() + ",年龄:" + one.getAge() + ",教室:" + one.room + ",学号:" + one.getId()); System.out.println("姓名:" + two.getName() + ",年龄:" + two.getAge() + ",教室:" + two.room + ",学号:" + two.getId()); }
2.当static关键字修饰成员方法时,该成员方法就成为了静态方法。静态方法不属于对象,而是属于类的。如果没有static关键字,那么必须首先创建对象,然后通过对象才能使用它。(本类的main()方法也不可使用,因为main()方法同样是静态方法,静态方法不可调用非静态方法。)
如果有了static关键字,那么不需要创建对象,直接就能通过类名称来使用它。
public class MyClass { // 成员方法只能通过对象使用 public void method(){ System.out.println("这是一个普通的成员方法。"); } // 静态方法可以通过对象名调用,也可以直接通过类名称调用 public static void methodStatic(){ System.out.println("这是一个静态方法。"); } }
MyClass obj = new MyClass(); // 首先创建对象 // 然后才能调用没有static关键字的非静态成员方法 obj.method(); // 静态方法可以由对象调用 // 这种写法在编译之后也会被javac翻译成为“类名称.静态方法名” obj.methodStatic(); // 也是正确写法,不推荐 // 也可以直接类名调用 MyClass.methodStatic(); // 正确,推荐 // 回顾知识点,匿名内部类 new MyClass().methodStatic(); // 正确 }
无论是成员变量,还是成员方法。如果有了static,都推荐使用类名称来调用。
静态变量:类名称.静态变量
静态方法:类名称.静态方法()
而对于本类的静态方法,可以省略类名称。
注意事项:
1.静态不能直接访问非静态。
原因:因为在内存当中,是先有的静态内容,后有的非静态内容。“先人不知道后人,但是后人知道现任。”
在本类中:
非静态方法中可以访问静态/非静态变量、静态/非静态方法。
静态方法中只能访问静态变量、静态方法。
但不要混淆,这是在本类里的限制,其他类还是可以直接类名.静态变量/方法调用。
2.静态方法当中不能用this。
原因:this代表当前对象,通过谁调用的方法,谁就是当前对象。但是静态和对象没关系。
public class MyClass { int num; // 成员变量 static int numStatic; // 静态变量 // 成员方法只能通过对象使用 public void method(){ System.out.println("这是一个普通的成员方法。"); // 非静态成员方法可以访问成员变量 System.out.println(num); // 非静态成员方法可以访问静态变量 System.out.println(numStatic); // 非静态成员方法可以访问静态方法,同样也可以访问非静态方法 methodStatic(); } // 静态方法可以通过对象名调用,也可以直接通过类名称调用 public static void methodStatic(){ System.out.println("这是一个静态方法。"); // 静态方法可以访问静态变量 System.out.println(numStatic); // 静态方法不可以访问非静态成员变量【重点】 //System.out.println(num); // 错误写法! // 静态方法不可以访问非静态成员方法【重点】 // method(); // 静态方法中不能使用this关键字 // System.out.println(this); } }