static也叫静态,可以修饰成员变量、成员方法。
成员变量
按照有无static分为两种:
- 类变量:static修饰,属于类,与类一起加载一次,在内存中只有一份,会被类的全部对象共享
 - 实例变量(对象变量):无static修饰,属于每个对象的。
 
代码举例:
//先创建一个学生类
public class Student {
    //类变量
    static String name;
    //实例变量(对象变量)
    int age;
}
//测试
public class Test {
     public static void main(String[] args) {
        //1、类变量的使用
        //类名.类变量
        Student.name="袁华";
        //对象.类变量(不推荐)
        Student s1=new Student();
        s1.name="马冬梅";
        Student s2=new Student();
        s1.name="秋雅";
        System.out.println(s1.name); //输出秋雅
        System.out.println(Student.name);  //输出秋雅
        //2、实例变量的使用:属于每个对象的变量
        //对象、实例变量(不能通过类名.变量名访问)
        s1.age=23;
        s2.age=18;
        System.out.println(s1.age);  //输出23
        System.out.println(s2.age);  //输出18
    }
} 
一开始先将Test.class加载到方法区,然后main方法入栈,运行到Student.name="张三"会将Student.class加载到方法区,并检查是否有类变量,如果有也会将类变量立即加载到堆内存中,初始值为null,然后赋值成 袁华

然后在堆内存中创建学生对象,学生变量s1指向这个对象,然后执行 s1.name=“马冬梅” 会在s1指向的对象中去寻找这个变量,如果没有这个变量,则通过类的地址去寻找Student.class,然后通过这个寻找到name并赋值成 “马冬梅”

同理s2的创建和修改和上面一样

最后s1和s2的name都指向同一个,所以最后输出的名字都是“秋雅”。
下面再看实例变量age的变化:
s1.age=23会通过s1找到第一个学生对象,将其变量age的值改为23;同理s2也是如此

类变量的应用场景
在开发中,如果某个数据只需要一份,且希望能够被共享(访问、修改),则该数据可以定义成类变量来记住。例如,一个类可以记住自己创建了多少个对象,如下图

成员方法
按照有无static分为两种:
- 类方法:static修饰,属于类
 - 实例方法:无static修饰,属于每个对象的。
 
代码举例:
public class Student {
    double score;
    //类方法
    public static void printHelloWorld(){
        System.out.println("Hello World");
    }
    //实例方法
    public void printPass(){
        System.out.println("成绩"+(score>=60?"及格了":"没及格"));
    }
}
//测试
public class StaticTest {
    public static void main(String[] args) {
        //1、类方法的使用
        //类名.类方法
        Student.printHelloWorld();
        //对象.类方法(不推荐)
        Student s1=new Student();
        s1.printHelloWorld();
        //2、实例方法的使用:属于每个对象的方法
        //对象.实例方法(不能通过类名.方法名访问)
        s1.printPass();
    }
} 
一开始先将Test.class加载到方法区,然后main方法入栈,运行到Student.printHelloWorld()会将Student.class加载到方法区,然后通过学生类找到printHelloWorld()方法,进行打印

  然后在堆内存中创建学生对象,学生变量s1指向这个对象,然后执行 s1.printHelloWorld() 时,会通过s1找到它指向的学生对象,然后通过学会对象找到Student这个类,通过这个类找到这个printHelloWorld()方法 。如图
实例方法也是如此,但它会访问这个对象的一些变量,所以不能通过类名调用(通过类名调用就不知道访问哪个对象的变量了)。
补充:main方法也是类方法,也是通过类名.main进行调用的
应用场景
类方法最常见的应用场景是做工具类:提高了代码复用;调用方便,提高了开发效率
注意事项
1. 类方法中可以直接访问类成员,不可以直接访问实例成员
public class Student {
    static String schoolname;//类变量
    double score;//实例变量
    //类方法
    public static void printHelloWorld(){
        //同一个类中,访问类成员,可以省略类名
        schoolname="张三";
        printHelloWorld2();
//        score=12.0;//报错
//        printPass();//报错
    }
    //类方法
    public static void printHelloWorld2(){
        System.out.println("Hello World");
    }
    //实例方法
    public void printPass(){
        System.out.println("成绩"+(score>=60?"及格了":"没及格"));
    }
} 
2. 实例方法中既可以直接访问类成员,也可以直接方法实例成员
public class Student {
    static String schoolname;//类变量
    double score;//实例变量
    //类方法
    public static void printHelloWorld2(){
        System.out.println("Hello World");
    }
    //实例方法
    public void printPass(){
        schoolname="李四";
        printHelloWorld2();
        printPass2();
        System.out.println(score);
    }
    //实例方法
    public void printPass2(){
        
    }
} 
3. 实例方法中可以出现this关键字,类方法中不可以出现this关键字
因为实例方法用this时会拿到这个对象,而类方法拿不到对象
应用知识
1. 代码块
代码块是类的5大成分之一(成员变量、构造器、方法、代码块、内部类)。
代码块分为两种:
- 静态代码块 
  
- 格式:static{}
 - 特点:类加载时自动执行,由于类只加载一次,所以静态代码块也只会执行一次
 - 作用:完成类的初始化,例如:对类变量的初始化赋值。 
public class Student { static int number=80; static{ System.out.println("静态代码块执行了"); } } //测试 public class StaticTest { public static void main(String[] args) { System.out.println(Student.number); } } //输出 静态代码块执行了 80 
 - 实例代码块 
  
- 格式:{}
 - 特点:每次创建对象时,执行实例代码块,并在构造器前执行
 - 作用:和构造器一样,都是用来完成对象的初始化的。例如对实例变量进行初始化赋值
 
 
2. 单例模式
确保一个类只有一个对象
写法
- 把类的构造器私有
 - 定义一个类变量记住类的一个对象
 - 定义一个类方法,返回对象 
public class A { //2.定义一个类变量记住类的一个对象 private static A a=new A(); //1.私有类的构造器 private A() { } //3.定义一个类方法,返回对象 public static A getObject(){ return a; } } 
实现方式
- 饿汉式单例:拿到对象时,对象早已经创建好了。上面便是。
 - 懒汉式单例:拿到对象时,才开始创建对象。 
public class B { //1.类的构造器私有 private B() { } //2.定义一个类变量,用户存储这个类的一个对象 private static B b; //3.定义一个类方法,要保证第一次调用时才创建一个对象,后面调用时都会用这同一个对象 public static B getObject(){ if(b==null){ b=new B(); } return b; } } 






![P8749 [蓝桥杯 2021 省 B] 杨辉三角形](https://img-blog.csdnimg.cn/direct/1dbb32b2758a443c8d93343ee5562579.jpeg#pic_center)












