面向对象知识汇总(2)

Day 2

问题五:static

1. 类的成员变量

  • 非静态成员变量/普通成员变量:属于对象的,每实例化一个对象,都会有一个对应的非静态成员变量,每个对象都有;通过对象的引用+点号来访问
  • 静态成员变量:属于类的,不属于对象的;类名+点号来访问静态成员变量;静态成员变量随着类被加载而创建,类被销毁而销毁

简单来说,静态成员变量只依赖于类的存在而存在,只要类存在,静态成员变量便存在,静态成员变量不是某个具体的对象所专有的,是所有对象共享的;而非静态成员变量,依赖于实例化对象

类变量存储在方法区当中

2. static修饰成员方法

Java中,被static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的,静态成员一般是通过静态方法来访问的

  • 静态成员方法通过类名.静态方法名(.....)调用
  • 不可以在静态方法中访问任何非静态成员变量(由于this引用指向的是调用成员方法时引用的对象,于是this引用是该对象特有的,并不是静态的,于是不可以在静态方法中使用this)
  • 静态方法中不能调用任何非静态方法(非静态方法中有this引用的存在)
  • 静态方法无法重写,不能用来实现多态

3. static成员变量的初始化

静态成员变量一般不会放在构造方法中来初始化,构造方法中初始化的是与对象相关的实例属性

  • 就地初始化
  • 静态代码块初始化

【总结】

静态成员变量是所有由类创建得到的对象所共有的,是属于类的,静态成员变量通过静态成员方法去访问

问题六:代码块

  • 普通代码块:定义在方法中的代码块
  • 构造代码块/实例代码块:定义在类中的代码块(不加修饰符),一般用于初始化实例成员变量
    • 实例代码块只有在创建对象时才会执行
  • 静态代码块:使用static定义的代码块称为静态代码块,一般用于初始化静态成员变量
    • 静态代码块只会在类创建的时候执行一次
    • 静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的
    • 如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行
public class Student{
    private String name;
    private String gender;
    private int age;
    private double score;
    private static String classRoom;
    //实例代码块
    {
        this.name = "bit";
        this.age = 12;
        this.gender = "man";
        System.out.println("I am instance init()!");
    } 

    // 静态代码块
    static {
        classRoom = "bit306";
        System.out.println("I am static init()!");
    }
   
    public Student(){
        System.out.println("I am Student init()!");
    }
    
    public static void main(String[] args) {
        Student s1 = new Student();
        Student s2 = new Student();
        
         { 
            //直接使用{}定义,普通方法块
            int x = 10 ;
            System.out.println("x1 = " +x);
        } 
    }
}

问题七:内部类

在 Java 中,可以将一个类定义在另一个类或者一个方法内部,前者称为内部类,后者称为外部类

  • 定义在class 类名{}花括号外部的,即使是在一个文件里,都不能称为内部类
  • 内部类和外部类共用同一个Java源文件,但是经过编译之后,内部类会形成单独的字节码文件

1. 内部类分类

public class OutClass {
    // 成员位置定义:未被static修饰 --->实例内部类
    public class InnerClass1{
    } 
    // 成员位置定义:被static修饰 ---> 静态内部类
    static class InnerClass2{

    }
    public void method(){
        // 方法中也可以定义内部类 ---> 局部内部类:几乎不用
        class InnerClass5{
        }
    }
}
  • 成员内部类:在外部类中,内部类定义位置与外部类成员所处的位置相同
    • 普通内部类/实例内部类:未被static修饰的成员内部类
    • 静态内部类:被static修饰的成员内部类
  • 局部内部类:方法中定义的内部类
  • 匿名内部类

2. 实例内部类

class OuterClass {
    public int data1 = 1;

    class InnerClass {
        public int data1 = 11;
        public void test() {
            System.out.println(data1);//11
            System.out.println(this.data1);//11
            System.out.println(OuterClass.this.data1);//1
            //实例内部类中包含了两个this,一个是外部类的this,一个是实例内部自己的this
        }
    }
    
    public void func() {
        InnerClass innerClass = new InnerClass();
        innerClass.test();
    }

}

public class Test {
    public static void main(String[] args) {
        OuterClass out = new OuterClass();
        out.func();

        OuterClass.InnerClass innerClass = out.new InnerClass();
        OuterClass.InnerClass innerClass1 = new OuterClass().new InnerClass();
        innerClass.test();
    }
}
  • 外部类中的任何成员都可以在实例内部类方法中直接访问
  • 实例内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束
  • 在实例内部类方法中访问同名的成员时,优先访问自己的,如果要访问外部类同名的成员,必须:外部类名称.this.同名成员来访问,实例内部类的非静态方法中包含了一个指向外部类对象的引用(this)
  • 外部类方法中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象
  • 实例内部类对象必须在先有外部类对象前提下才能创建

3. 静态内部类

class OuterClass {
    public int data1 = 1;

    static class InnerClass {
        public static int data6 = 6;
        public void test() {
            OuterClass outerClass = new OuterClass();
            System.out.println(outerClass.data1);
            System.out.println(data6);
        }
    }
    public void func() {
        InnerClass innerClass = new InnerClass();
        innerClass.test();
    }

}

public class Test {
    public static void main(String[] args) {
        OuterClass.InnerClass innerClass = new OuterClass.InnerClass();
        innerClass.test();
    }

}
  • 在静态内部类中只能访问外部类中的静态成员,不可以直接访问外部类对象的非静态成员变量,因为外部类对象的成员依赖外部类对象,可以先创建外部类对象,再进行访问
  • 创建静态内部类对象时,不需要先创建外部类对象

4. 局部内部类

定义在外部类的方法体或者{}中,该种内部类只能在其定义的位置使用,一般使用的非常少

public class OutClass {
    int a = 10;
    public void method(){
        int b = 10;
        // 局部内部类:定义在方法体内部
        // 不能被public、static等访问限定符修饰
        class InnerClass{
            public void methodInnerClass(){
                System.out.println(a);
                System.out.println(b);
            }
        }
        // 只能在该方法体内部使用,其他位置都不能用
        InnerClass innerClass = new InnerClass();
        innerClass.methodInnerClass();
    }
    public static void main(String[] args) {
        // OutClass.InnerClass innerClass = null; 编译失败
    }
}

5. 匿名内部类

5.1 匿名对象
public class Test3 {
    public void func() {
        System.out.println("func()");
    }
    public static void main(String[] args) {
        Test3 test3 = new Test3();
        test3.func();
        test3.func();

        new Test3().func();//匿名对象
    }
}

如果以后的场景是使用一次对象,那么就使用匿名对象

5.2 匿名内部类
interface InterfaceA {
    void func();
}

class TestA implements InterfaceA{
    @Override
    public void func() {
        System.out.println("我是重写的funcA方法");
    }
}

public class Test {

    public static void main(String[] args) {
        TestA testA = new TestA();//创建类
        
        InterfaceA interfaceA = new InterfaceA() {
            @Override
            public void func() {
                System.out.println("hello");
            }
        };
        //匿名内部类
        //这部分可以看做是一个类,实现了InterfaceA接口,并且重写了接口当中的方法

        interfaceA.func();
        
        new InterfaceA() {
        	@Override
            public void func() {
                System.out.println("hello hello");
            }
        }.func();
        //上述写法也可以
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胖了你都蹲不下来撸猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值