目录
当我们定义一个类时,如果其中的某个成员变量不需要改变,我们可以用static来修饰它,称为静态成员变量,静态成员变量最大的特性是:不需要某个具体的对象,是所有对象所共享的。
例如:
- class Student{
- public String name;
- public int age;
- public static String classRoom = "计科211";
-
- public Student(String name, int age) {
- this.name = name;
- this.age = age;
- }
- }
- public class Test {
- public static void main(String[] args) {
- Student student1 = new Student("zhangsan",10);
- Student student2 = new Student("lisi",15);
- System.out.println(Student.classRoom);
- System.out.println(Student.classRoom);
- }
- }
我们也可以画图理解:
静态成员变量特性:
- 不属于某个具体的对象,是类的属性,所有对象共享。
- 可以通过对象访问,也可以通过类名访问,但最好是类名访问。
- 它的生命周期伴随类的一生。
- final定义的常量不能修改,final定义的静态常量不能修改且必须初始化。
当static修饰成员方法时,就称为静态方法,也叫类方法。
例:
- class Student{
- public String name;
- public int age;
- public static String classRoom = "计科211";
-
- public Student(String name, int age) {
- this.name = name;
- this.age = age;
- }
- public static void Func(){
- System.out.println("静态方法");
- }
- }
- public class Test {
-
-
- public static void main(String[] args) {
- Student.Func();
- }
- }
注:
- 静态方法的调用不需要引用对象,直接使用类名调用,因此静态方法内不能直接访问非静态的变量或方法。
- 在静态方法中可以创建对象来间接访问非静态数据。
使用 {} 定义的一段代码叫做代码块,可以分为一下几种:
- 普通代码块(本地代码块)
- 构造块(实例代码块)
- 静态块
- 同步代码块
定义在方法内部的代码块,一般很少用到:
-
- public static void Func(){
- System.out.println("静态方法");
-
- {
- System.out.println("本地代码块");
-
- }
- }
-
定义在类的内部,方法的外部。用来初始化实例成员变量,只有在创建对象时才会调用。
- class Student{
- public String name;
- public int age;
- public static String classRoom = "计科211";
-
- {
- this.name = "hh";
- this.age = 10;
- }
-
- }
- public class Test {
-
-
- public static void main(String[] args) {
- }
- }
static修饰的代码块,一般用来初始化静态成员变量。
- class Student{
- public String name;
- public int age;
- public static String classRoom;
-
-
- static{
- classRoom = "计科211";
- }
-
- }
- public class Test {
-
-
- public static void main(String[] args) {
- Student.Func();
- }
当实例代码块、静态代码块、和构造方法同时出现时:
其先执行静态代码块,然后执行实例代码块,最后执行构造方法。
- class Student{
- public String name;
- public int age;
- public static String classRoom = "计科211";
-
- public Student(String name, int age) {
- this.name = name;
- this.age = age;
- System.out.println("带有两个参数的构造方法");
- }
- public static void Func(){
- System.out.println("静态方法!");
- }
-
- {
- this.name = "haha";
- System.out.println("实例代码块!");
- }
-
- static{
- classRoom = "计科212";
- System.out.println("静态代码块!");
- }
-
- }
- public class Test {
-
- public static void main(String[] args) {
- Student student = new Student("hehe",10);
-
- }
- }
当有两个静态方法时:
- class Student{
- public String name;
- public int age;
- public static String classRoom = "计科211";
-
- public Student(String name, int age) {
- this.name = name;
- this.age = age;
- System.out.println("带有两个参数的构造方法");
- }
- public static void Func(){
- System.out.println("静态方法!");
- }
-
- {
- this.name = "haha";
- System.out.println("实例代码块!");
- }
-
- static{
- classRoom = "计科212";
- System.out.println("静态代码块!");
- }
-
- }
- public class Test {
-
- public static void main(String[] args) {
- System.out.println(Student.classRoom);
- }
- }
总结:
- 先执行静态的(加载了类就会被执行),且静态块只会执行一次。
- 如果有多个静态的,那么看定义顺序。
- 如果没有实例化对象,那么就只会执行静态的。
- 再执行实例化块,有多个实例化数据时就要看定义的顺序。
- 再执行构造方法。
- 一个类定义在另一个类或者方法的内部,前者称为内部类,后者称为外部类。
- 内部类也是封装的一种体现。
- 一个文件里面的不是内部类,只有一个类中的才是。
- class OuterClass{
-
- class InnerClass{
-
- }
- }
- public class Test {
-
- }
- class OuterClass{
-
- public int data1 = 1;
- private int data2 = 2;
- public static int data3 = 3;
-
- class InnerClass{
- public int data4 = 4;
- private int data5 = 5;
- public int data1 = 111;
- public InnerClass() {
- System.out.println("实例内部类的构造方法!");
- }
- public void innerFunc(){
- System.out.println("实例内部类的普通方法!");
- System.out.println(data1);
-
- //访问与内部类同名的外部类的成员变量
- System.out.println("外部类:"+ OuterClass.this.data1);
- System.out.println(data2);
- System.out.println(data3);
- System.out.println(data4);
- System.out.println(data5);
- }
- }
- }
- public class Test {
- public static void main(String[] args) {
- //OuterClass outerClass = new OuterClass();
- //OuterClass.InnerClass innerClass = outerClass.new InnerClass();
-
- //实例化内部类
- OuterClass.InnerClass innerClass = new OuterClass().new InnerClass();
-
- innerClass.innerFunc();
- }
- }
总结:
- 实例内部类不能定义静态的成员变量,如果要定义,就要加final修饰。
- 实例内部类中不能定义静态的成员方法。
- 如果在实例内部类内访问同名的外部类由static修饰的成员变量时,直接外部类类名.成员变量。
- 实例内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束。
- 会生成字节码文件: 外部类$内部类。
- class OuterClass{
- public int data1 = 1;
- private int data2 = 2;
- public static int data3 = 3;
-
- static class InnerClass{
- public int data4 = 4;
- private int data5 = 5;
- public static int data6 = 6;
- private OuterClass outerClass;
-
- public InnerClass(OuterClass outerClass){
- System.out.println("静态内部类的构造方法!");
- this.outerClass = outerClass;
- }
- public void func(){
- System.out.println("func方法执行了!");
-
- //访问非静态外部类成员变量
- System.out.println(outerClass.data1);
- System.out.println(outerClass.data2);
-
- System.out.println(data3);
- System.out.println(data4);
- System.out.println(data5);
- System.out.println(data6);
-
- }
- }
- }
- public class Test2 {
-
- public static void main(String[] args) {
-
- //实例化静态内部类
- OuterClass.InnerClass innerClass = new OuterClass.InnerClass(new OuterClass());
- innerClass.func();
- }
- }
注:
- 在静态内部类中只能访问外部类中的静态成员,不能在静态内部类中直接访问外部类的非静态的数据成员,可以通过实例化外部类对象来间接访问。
- 创建静态内部类对象时,不需要先创建外部类对象。
- 局部内部类定义在方法体内部,之饿呢过在该方法体内使用,其他位置不能使用。
- 不能被public、static等访问限定符修饰。
- 也有独立的字节码文件,命名格式:外部类名字$内部类名字。
- public class Test2 {
-
- public static void fun(){
- class A{
- public void test(){
- System.out.println(1);
- }
- }
- A a = new A();
- a.test();
- }
-
- public static void main(String[] args) {
-
- fun();
-
- }
- }
- class Person{
- public String name;
- public int age;
-
- public void test(){
- System.out.println("lisi");
- }
- }
- public class Test2 {
-
- public static void main(String[] args) {
- //匿名对象,只能使用一次
- new Person().test();
-
- new Person(){
- @Override
- public void test() {
- System.out.println("77777");
- }
- }.test();
- }
- }
- class Person{
- public String name;
- public int age;
-
- public Person(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- @Override
- public String toString() {
- return "Person{" +
- "name='" + name + '\'' +
- ", age=" + age +
- '}';
- }
- }
- public class Test3 {
- public static void main(String[] args) {
- Person person = new Person("zhangsan",10);
- System.out.println(person);
- }
- }
当我重写ToString函数之后,编译器就会调用我重写的函数,可以实现对对象的打印,