成员内部类、静态内部类、匿名内部类、

成员内部类

成员内部类:顾名思义、成员中的类(类种类)。
同时在编译后会出现【外部类名.class 和 外部类名$内部类名.class文件】这两个字节码文件
话不多少先上代码介绍:

class Demo {
    
    
	class Demo1 {
    
    
	}
}

特点:

  1. 内部类写在一个类中,同时创建对象需要依赖于外部类对象。
  2. 可以为外部类提供必要的内部功能组件。
  3. 内部类可以直接访问外部类的私有成员,从而不会去破坏封装。
  4. 编译之后会生成独立的字节码文件。(详情看下面)

内部类访问外部类

1.可以访问任何属性和方法【包括私有的、静态的】
  访问方式有2种 :直接写属性名或者是外部类.this.属性【方法】
1.1直接写属性名
  这种方式有个缺点:如果内部类定义的属性【方法】和外部类一样,会发生隐藏现象,取得的是内部类的值,若想取得外部类的值,采用外部类.this.属性【方法】
1.2若采用直接写属性名获得外部类值,其实本质还是外部类.this.属性

public class InnerClass {
    
    
	public static void main(String[] args) {
    
    
  	//创建内部类对象
  	TestInner.Inner in = new  TestInner().new Inner();
  	in.print();
 	}
}
class TestInner {
    
    
	private int a = 2; 
	class Inner {
    
    
		public void print() {
    
    
			System.out.println(TestInner.this.a);
			System.out.println(a);
		}
	}
}
//结果:2
//     2

【注意】:

1.可以定义非静态属性和方法,不可以定义static修饰的属性和方法,可以定义static final修饰的编译期变量【不用加载类的字节码】

1.1为什么不可以定义static修饰的属性和方法?

首先内部类是外部类的一个成员,只有当外部类初始化的时候,内部类才能初始化,静态变量属于类级别,在类加载的时候就初始化,所以两者本身在语法上就有矛盾。

1.2为什么可以定义static final修饰的变量?

首先要先知道static final修饰的变量叫做常量,常量分为编译期常量和非编译期常量
      编译期常量:在程序编译阶段【不需要加载类的字节码】,就可以确定常量的值
      非编译期常量:在程序运行阶段【需要加载类的字节码】,可以确定常量的值

public class OutterClass {
    
       
    class Inner{
    
    
        int a = 0;//非静态变量
        static int b = 0;//静态变量【报错!!】
        static final int c = 0;//编译期常量,不需要类加载
        static final Integer d = new Integer(2);//非编译期常量,需要类加载【报错!!】
    } 
    public static void main(String[] args) {
    
    
        System.out.println(OutterClass.Inner.b);
        System.out.println(OutterClass.Inner.c);
        System.out.println(OutterClass.Inner.d);
    }
}

b属性是静态的,它需要加载类的字节码Inner类,由于它是在OutterClass内部,需要外部类实例化才能加载,但是调用处没有实例化外部类,所以Inner也不会类加载,所以报错!!
c属性是编译期常量,它不需要加载类的字节码Inner类,所以不会报错
d属性是非编译期常量。它需要加载类的字节码Inner类,所以报错!!

2.内部类可以被任何访问修饰符修饰

因为它也是外部类的一个成员。

静态内部类

简介:静态内部类 顾名思义内部静态的类,即:被static修饰的类【因为内部类是外部类的成员,因此内部类可以被任何访问修饰符所修饰,同时也可以被static所修饰。】
【注意】:
1、因为静态内部类是静态的,因此同理无需依赖于外部类对象的创建才可以做访问。
2、静态内部类可以访问外部类的所有属性和方法。
3、静态内部类中实例方法必须通过创建内部类对象才可以访问。

class Demo {
    
    
	public static void main(String[] args) {
    
    
		Outer.Inner in = new Outer.Inner();
		in.m1();
		Outer.Inner.m2();
	}
}
class Outer {
    
    
	private int a = 1;
	static class Inner {
    
    
		public void m1() {
    
    
			System.out.println(a);
		}
		public static void m2() {
    
    
			System.out.println("我是静态内部类的静态方法,无法访问非静态属性。");
		}
	}
}
/**
* 执行结果:
* 1
* 我是静态内部类的静态方法,无法访问非静态属性。
*/

匿名内部类

简介:没有类名的内部类

interface AnonymousInnerClass {
    
    
	default void m1() {
    
    
   		System.out.println("我是匿名内部类");
 	}

}
class Test {
    
    
	//第一种创建对象时创建匿名内部类。
	AnonymousInnerClass ais = new AnonymousInnerClass() {
    
    
		public void m1() {
    
    
			System.out.println("我是匿名内部类");
		}
	};
	ais.m1();
	//第二种直接new对象创建匿名内部类,同时调用里面的方法。
	new AnonymousInnerClass() {
    
    
		public void m1() {
    
    
	   		System.out.println("我是匿名内部类");
	 	} 
	}.m1();
	//第三种匿名对象直接调用
	finalAnonymousInner(new AnonymousInnerClass() {
    
    
		public void m1() {
    
    
	     		System.out.println("我是匿名内部类");
	   	}
	});
	public static void finalAnonymousInner(AnonymousInnerClass ais) {
    
    
		ais.m1();
	}
}

局部内部类

简介:定义在外部类方法中,作用范围和创建对象范围仅限于当前方法。
1、局部内部类访问外部类当前方法中的局部变量时,因无法保障生命周期于自身相同,变量必须修饰为final(此时为常量,加载时位于【常量池】中)。
2、限制类的使用范围。

class Outer {
    
    
	int a = 2; 
	public void m1() {
    
    
		final int a = 1;
	}
	@Test
	public void TestInner() {
    
    
		int a = 3;
		class Inner {
    
    
			public void m2() {
    
    
				System.out.println("访问外部类中的属性a = " + Outer.this.a);
				System.out.println("访问外部类中的m1方法中的属性a = " + a);
				System.out.println("访问外部类中的m2方法中的局部内部类Inner中的属性a = " + this.a);
			}
		}
		Inner in = new Inner();//实例化局部内部类Inner的对象。
		in.m2();//调用方法
	}
}
/**
* 执行结果:访问外部类中的属性a = 2
* 访问外部类中的m1方法中的属性a = 1
* 访问外部类中的m2方法中的局部内部类Inner中的属性a = 3
/

同时再补充一点,在外部类如何访问静态内部类的非静态方法:

public class TestInnerClass {
    
    
    public static void main(String[] args) {
    
    
        Inner inner1 = new TestInnerClass().new Inner();
        inner1.print();
        inner1.print("inner1");
        System.err.println(inner1.print(1));

        Inner2 inner2 = Inner2.print();
        inner2.print("inner2");
        System.err.println(inner2.print(1));
    }

    public static void print(){
    
    
        System.out.println("TestInnerClass");
    }

    public void print2(){
    
    
        System.out.println("TestInnerClass");
    }

    class Inner {
    
    

        public void print() {
    
    
            System.out.println("inner1");
        }

        private void print(String b) {
    
    
            System.out.println(b);
        }

        public int print(int a) {
    
    
            return a;
        }
    }

    static class Inner2 {
    
    
        int a = 0;
        public static Inner2 print() {
    
    
            TestInnerClass.print();
            TestInnerClass aClass = new TestInnerClass();
            aClass.print2();
            System.out.println("inner2");
            return new Inner2();
        }

        private void print(String b) {
    
    
            System.err.println(b);
        }

        public int print(int a) {
    
    
            return a;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_16733389/article/details/105992162