成员变量:静态成员元变量(又称类变量/类成员)、 非静态成员变量(又称普通成员变量)
Static修饰成员变量
Static修饰的成员变量称为静态成员变量,静态成员变量最大的特性:不属于某个具体的对象,是所有对象所共享的。
静态成员变量特性
1.不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中;
2.既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问;
3.类变量存储在方法区当中;
4.生命周期伴随类的一生(即:随类的加载而创建,随类的卸载而销毁);
成员方法:静态成员方法(又称类方法)、 非静态成员方法
注意:
1、在静态成员方法内部不能直接调用非静态成员方法,调用非静态的成员必须依赖于对象的引用;
2、在静态方法内部不能直接使用非静态的数据成员(因为非静态的数据成员是属于对象的)只要是非静态的数据成员都需要通过对象的引用才能调用;
3、静态方法里面是不能使用this的,普通成员方法内部是可以使用静态成员方法的;
Static修饰成员方法
一般类中的数据成员都设置为private,而成员方法设置为public。
Java中被static修饰的成员方法称为静态成员方法,是类方法,不是某个对象特有的,静态成员一般是通过静态方法来访问的。
静态成员方法特性:
1.不属于某个具体的对象,是类方法;
2.可以通过对象调用,也可以通过类名.静态方法名(...)方式调用,更推荐使用后者方式;
3.不能在静态方法中访问任何非静态成员变量;
4.静态方法中不能调用任何非静态方法,因为静态方法有this参数,在静态方法中调用的时候无法传递this引用;
(建议:获取静态的成员变量或者是设置静态的成员变量,此时的方法最好是静态的,否则若是非静态的还要实例化对象,此时会显得更繁琐)
5.静态方法无法重写,不能用来实现多态;
Static成员变量初始化
注意:静态成员变量一般不会放在构造方法中来初始化,构造方法中初始化的是与对象相关的实例属性
对静态成员变量的初始化:
直接赋值
默认初始化
可以提供get和set方法来进行初始化
在构造对象的时候,可以在构造方法中进行赋值(不建议这么写)
通过代码块进行赋值
class Student{
public String name;
public int age;
//直接赋值
public static String classRoom = "Java班";
//一个教室可以存在多名学生因此使用static修饰即可 此时方法区有一个属性classRoom
//默认初始化
private static int size;
//提供get和set方法来进行初始化
public static int getSize() {
return size;
}
public static void setSize(int size) {
Student.size = size;
}
//在构造对象的时候,可以在构造方法中进行赋值(不建议这么写)
public Student(String name, int age,int si) {
this.name = name;
this.age = age;
size = si;
}
}
代码块概念以及分类
使用{}定义的一段代码称为代码块,根据代码块定义的位置以及关键字,又可分为以下四种
普通代码块、构造块、静态块、同步代码块
普通代码块
一般特指定义在方法内部的代码块,这块代码的执行不需要条件
主要是用来区分某个代码作用域,不常用
public static void func(){
//....
{
System.out.println("定义在方法内部的代码块 普通代码块");
}
}
构造代码块(又称非静态代码块/实例代码块)
构造块:定义在类中的代码块(不加修饰符)也叫:实例代码块,构造代码块一般用初始化实例成员变量。(在类里面方法外面,一般用来初始化非静态的数据成员)
在执行构造方法之前,先执行实例代码块-->因此在实例代码块中无论如何赋值都无所谓,因为之后还会执行构造方法(前提:构造方法含参数)。
(可以简单认为:编译器编译好代码之后会把非静态代码块的东西放到构造方法的最前面)
如果都是非静态的,那么看定义的顺序,谁在后就是谁。
{
name = "星辰大海";
System.out.println("非静态代码块/实例代码块/构造代码块===> 初始化非静态的数据成员");
}
静态代码块
使用static定义的代码块称为静态代码块,一般用于初始化静态成员变量或提前准备一些数据。
static {
System.out.println("静态代码块-->初始化静态的数据成员/提前准备一些数据");
}
注意:
1.静态代码块不管生成多少个对象,都只会被执行一次;
2.静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的;
3.如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后顺序依次执行;
4.实例代码块只有在创建对象时才会被执行;
实例代码详细解析
class Student{
public String name;
public int age;
//直接赋值
public static String classRoom = "Java班";
//一个教室可以存在多名学生因此使用static修饰即可 此时方法区有一个属性classRoom
//静态成员变量不属于对象-->可以不用通过对象的引用来访问,直接可以通过类名就可以访问
//默认初始化
private static int size;
//提供get和set方法来进行初始化
public static int getSize() {
return size;
}
public static void setSize(int size) {
Student.size = size;
}
//在构造对象的时候,可以在构造方法中进行赋值(不建议这么写)
public Student(String name, int age,int si) {
this.name = name;
this.age = age;
size = si;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
System.out.println("带有2个参数的构造方法");
}
public Student(){
System.out.println("不带参数的构造方法");
}
{
name = "星辰大海";
System.out.println("非静态代码块/实例代码块/构造代码块===> 初始化非静态的数据成员");
}
static {
System.out.println("静态代码块-->初始化静态的数据成员/提前准备一些数据");
}
public void doClass(){
//4.普通成员方法内部可以使用静态的成员方法
func();
System.out.println(name+"上课");
}
public static void func(){
//注意 2.在静态方法内部,不能直接使用非静态数据成员,是要是非静态数据成员都需要通过对象的引用才能调用
//System.out.println(this.name); //err //3.静态方法里面是不能使用this的
//System.out.println(name); //err
System.out.println("static func()");
{
System.out.println("定义在方法内部的代码块 普通代码块");
}
}
public static void func2(){
func();//或者 Student.func(); //此时可以直接调用
}
}
public class NT231219 {
public static void main(String[] args) {
//由此可见静态代码块只会被执行一次
Student student1 = new Student();
System.out.println("=============");
Student student2 = new Student();
}
public static void main7(String[] args) {
//只要是这个类 被加载 静态代码块都会被执行的
Student.func();
//不管调用几次func静态代码块只会被执行一次
}
public static void main6(String[] args) {
Student student1 = new Student();
System.out.println(student1.name);
}
public static void main5(String[] args) {
//在调用构造方法之前会先执行实例代码块
Student student1 = new Student("星辰",18);
System.out.println(student1.name);
}
public static void main4(String[] args) {
Student student1 = new Student("星辰",18);
System.out.println(student1);
}
public static void main3(String[] args) {
System.out.println(Student.classRoom);
//说明:静态成员变量不属于对象,所以不用通过对象的引用来访问,直接可以通过类名进行访问
Student.func(); //静态成员方法不依赖于对象 可以使用类名直接调用
// 注意:1.在静态方法内部不可以直接调用非静态的成员方法
}
public static void main2(String[] args) {
System.out.println(Student.classRoom);//说明静态成员变量不属于对象
Student student1 = new Student("星辰",18);
student1.doClass();
student1.func();
}
public static void main1(String[] args) {
Student student1=new Student("张三",18);
Student student2=new Student("李四",18);
}
}