Static成员
目录
static使用情景
现在有一个学生类,我们定义一个学生需要姓名,年龄和班级,假设所有学生来自同一个班级,那么我们在写代码时,就要重复定义多个相同的班级变量,我们应该如何解决这个问题呢?
class Student {
//成员变量
private String name;
private int age;
public String classRoom;
//构造函数
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//Gettter Setter
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 class Tets1 {
public static void main(String[] args) {
Student student1 = new Student("A",15);
student1.classRoom = "106";
Student student2 = new Student("B",16);
student2.classRoom = "106";
Student student3 = new Student("C",15);
student3.classRoom = "106";
}
}
实际上,classroom = "106"这个变量我们只需要一份就好,这就用到了static。
静态成员变量
//成员变量
private String name;
private int age;
//public String classRoom;
public static String classRoom;
我们修改一下代码,调试一下就会发现:
对象中已经没有classRoom了,classRoom好像不属于对象了。那么classRoom被存到哪里了呢?我们引入一块新的内存,这块内存叫做方法区。
所有对象共用一个classRoom,对classRoom的访问方式也要做出相应的改变。 类名.classRoom
public class Tets1 {
public static void main(String[] args) {
Student student1 = new Student("A",15);
//student1.classRoom = "106";
Student student2 = new Student("B",16);
//student2.classRoom = "106";
Student student3 = new Student("C",15);
//student3.classRoom = "106";
Student.classRoom = "106";
}
}
被static修饰的成员变量叫做静态成员变量,没有被static修饰的成员变量叫做普通成员变量或者非静态成员变量。非静态成员变量都属于对象,访问方式就是 对象名.成员变量名。
静态成员变量的使用不依赖于对象。不实例化对象也能使用。
public static void main(String[] args) {
// Student student1 = new Student("A",15);
// //student1.classRoom = "106";
// Student student2 = new Student("B",16);
// //student2.classRoom = "106";
// Student student3 = new Student("C",15);
// //student3.classRoom = "106";
Student.classRoom = "106";
System.out.println(Student.classRoom);//106
}
静态成员变量最大的特性:不属于某个具体的对象,是所有对象所共享的。
静态成员方法
除了静态成员变量,你也可以写一个静态成员方法。
//成员方法
//普通成员方法
public void eat() {
System.out.println(this.name+" 正在吃饭!");
}
public void show() {
System.out.println("姓名:"+this.name+" 年龄:"+this.age);
}
//静态方法
public static void func() {
System.out.println("这是一个静态方法!");
}
同样静态成员方法的使用也不依赖于对象。调用方法:类名.func();
public class Tets1 {
public static void main(String[] args) {
Student.func();//这是一个静态方法!
}
}
在静态方法内部,不能直接调用非静态方法,因为静态方法依赖对象,而非静态方法不依赖对象,这也就解释了当时我们定义方法时为什么要加static
public static int add(int a,int b) {
return a + b;
}
public static void main(String[] args) {!
System.out.println(add(1, 2));
}
如果把add方法中的static去掉,就相当于在main这个静态方法里调用了add这个非静态方法,java会报错。要调用必须通过对象的引用。
public int add(int a,int b) {
return a + b;
}
public static void main(String[] args) {
Tets1 tets1 = new Tets1();
System.out.println(tets1.add(1,2));
}
同样,在静态成员方法里直接调用非静态成员变量也不行,也会报错。
//静态方法
public static void func() {
show();//error
System.out.println("这是一个静态方法!"+this.name);//error
}
静态方法中不能直接调用非静态的成员方法或者调用成员变量。相反非静态成员方法中是可以调用静态成员方法的。
静态成员变量初始化
在上面的代码中,我们可以在main方法中初始化
public static void main(String[] args) {
Student.classRoom = "106";
}
当静态成员变量被private修饰时,可以通过Getter和Setter进行初始化。
class Student {
//成员变量
private static String classRoom;
//Gettter Setter
public static String getClassRoom() {
return classRoom;
}
public static void setClassRoom(String classRoom) {
Student.classRoom = classRoom;
}
}
public class Tets1 {
public static void main(String[] args) {
Student.setClassRoom("106");
}
}
就地初始化
在定义时直接给出初始值
class Student {
//成员变量
private static String classRoom = "106";
……
静态代码块初始化
什么是代码块呢?
代码块
使用{}定义的一段代码称为代码块。可以分为四种:普通代码块、构造块、静态块、同步代码块(暂时不讲)。
普通代码块
就是定义在方法中的代码块,用的非常少。
public class Test2 {
public static void main(String[] args) {
//普通代码块
{
int x = 10;//x是局部变量,所用域是在{}里,出了{}就用不了了
System.out.println(x);
}
}
}
构造代码块
定义在类中的代码块(不加修饰符),也叫做实例代码块。一般用于初始化实例成员变量。
class Book {
//普通成员变量
private String name;
private int price;
//静态成员变量
public static String author;
//实例代码块 构造代码块 处于方法的外面,类的里面。
//用于初始化实例成员变量
{
this.name = "海的女儿";
this.price = 30;
System.out.println("实例代码块!");
}
//Getter和Setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
//构造方法
public Book() {
System.out.println("不带参数的构造方法!");
}
public Book(String name, int price) {
this.name = name;
this.price = price;
}
//普通成员方法
public void printBook() {
System.out.println("书名:"+this.name+" 价格:"+this.price);
}
//静态成员方法
public static void func() {
System.out.println("这是一个静态成员方法!");
}
}
public class Test2 {
public static void main(String[] args) {
Book book1 = new Book();
book1.printBook();
}
}
理论上来说,当我们创建一个实例化对象之后,程序会调用没有参数的构造方法,并且实例代码块会给book1初始化,所以程序会输出-->不带参数的构造方法!实例代码块!书名:海的女儿 价格:30
可当我们运行了这段代码之后,我们会发现输出结果和我们预想的不太一样。
这个输出结果说明,实例代码块会比构造方法先执行。跟实例代码块的位置无关,你可以动手试验一下。
静态代码块
class Book {
//普通成员变量
private String name;
private int price;
//静态成员变量
public static String author;
//实例代码块 构造代码块 处于方法的外面,类的里面。
//用于初始化实例成员变量
{
this.name = "海的女儿";
this.price = 30;
System.out.println("实例代码块!");
}
//静态代码块 对静态成员变量初始化
static {
author = "xxx";
System.out.println("静态代码块!");
}
//Getter和Setter
public String getName() {
return name;
}
……
此时程序的输出结果又是什么呢?
说明静态代码块比实例代码块更早执行。
综上:静态代码块先于实例代码块先于构造方法。
现在我们实例化第二个对象,看看程序的输出结果又是什么。
public class Test2 {
public static void main(String[] args) {
Book book1 = new Book();
book1.printBook();
System.out.println("===============");
Book book2 = new Book();
}
}
为什么是这个输出结果呢?
原因:不管生成几个对象,静态代码块都只执行一次。
一个类里面可以有多个构造代码块或者静态代码块
……
//静态代码块 对静态成员变量初始化
static {
author = "xxx";
System.out.println("静态代码块!2");
}
static {
author = "aaa";
System.out.println("静态代码块!1");
}
……
如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后顺序依次(合并)。
静态代码块只要类被加载就会被执行;实例代码块只有实例化对象的时候才被执行。
public static void main(String[] args) {
System.out.println(Book.author);
}
在main方法中只输出静态成员变量,输出结果为:
只调用了静态代码块,实例代码块并没有被调用。
原文地址:https://blog.csdn.net/kkkkkkk6666666/article/details/140531942
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!