【Java】内部类

内部类

内部类是一类特殊的类,指的是定义在一个类的内部的类。实际开发中,为了方便的使
用外部类的相关属性和方法,这时候我们通常会定义一个内部类。

内部类基本分类

上图所示,内部类共分为:匿名内部类局部内部类成员内部类。而成员内部类又可以分成非静态内部类静态内部类


内部类的概念

一般情况,我们把类定义成独立的单元。有些情况下,我们把一个类放在另一个类的内
部定义,称为内部类(innerclasses)。内部类可以使用public、default、protected 、private 以及static 修饰。而外部顶级类(我们以前接触的类)只能使用public 和default 修饰。

注意!!

内部类只是一个编译时概念,一旦我们编译成功,就会成为完全不同的两个类。对于一个名为Outer 的外部类和其内部定义的名为Inner 的内部类。编译完成后会出现Outer.classOuter$Inner.class 两个类的字节码文件。所以内部类是相对独立的一种存在,其成员变量/方法名可以和外部类的相同。


内部类的展示

/**内部类Outer*/
public class Outer {

    private int age = 100;

    private void show()
    {
        System.out.println("这是外部类!");
    }


    public static void main(String[] args) {
        Outer.Inner newname = new Outer().new Inner();
        newname.inner();
    }

	/**内部类Inner*/
    public class Inner{
        private int age = 110000;
		//内部类中可以声明与外部类同名的属性与方法	
		//非静态方法可以调用静态成员或者方法
        public void inner(){
            System.out.println(age);  //110000
            System.out.println(Test000.this.age);  //100
            show();  //这是外部类!
        }
    }
}

内部类的作用:
内部类提供了更好的封装。只能让外部类直接访问,不允许同一个包中的其他类直接访问。
内部类可以直接访问外部类的私有属性,内部类被当成其外部类的成员。但外部类不能访问内部类的内部属性。


非静态内部类

非静态内部类(外部类里使用非静态内部类和平时使用其他类没什么不同)

  • 非静态内部类对象必须寄存在一个外部类对象里。因此,如果有一个非静态内部类对象那么一定存在对应的外部类对象。非静态内部类对象单独属于外部类的某个对象

  • 非静态内部类可以直接访问外部类的成员,但是外部类不能直接访问非静态内部类成员。

  • 非静态内部类不能有静态方法、静态属性和静态初始化块。

  • 成员变量访问要点:(例子同上面代码)

    1. 内部类里方法的局部变量:变量名。
    2. 内部类属性:this.变量名。
    3. 外部类属性:外部类名.this.变量名。

非静态内部类对象创建方式

非静态内部类对象新建方式一共有两种:(针对Outer类内嵌Inner类举例)

//第一种方式
Outer.Inner in01 = new Outer().new Inner();  //此时in01作为内部类的对象可以实现方法或者成员调用

//第二种方式
Outer out02 = new Outer();
Inner in02 = out02.new Inner();  //此时in02作为内部类的对象可以实现方法或者成员调用

静态内部类

与大多数静态方法相似,静态内部类只需要在类名前加上static即可

static class ClassName
{
	//类体
}
  • 静态内部类可以访问外部类的静态成员,不能访问外部类的普通成员。
  • 静态内部类看做外部类的一个静态成员。
    (这点与静态方法不能调用非静态成员性质一致)

静态内部类对象创建方式

依旧针对Outer类内嵌Inner类举例:

//通过new 外部类名.内部类名() 来创建内部类对象
Outer.Inner in03 = new Outer.Inner();

-----------------------------------------------
//一些举例
Class Outer{
	public static  int a = 100;
	public int b = 200;
	static class Inner{
		puiblic void print(){  //静态内部类方法即便前面没有加static修饰也会被定义为静态方法
			System.out.println(a); //可以正常输出100
			System.out.println(b);  //静态方法不能调用非静态属性,这行代码会报错
		}
	}
}

匿名内部类

Java 中可以实现一个类中包含另外一个类,且不需要提供任何的类名直接实例化。主要是用于在我们需要的时候创建一个对象来执行特定的任务,可以使代码更加简洁。匿名类是不能有名字的类,它们不能被引用,只能在创建时用 new 语句来声明它们。

//语法体
new 父类构造器(实参类表) \实现接口() 
{
	//匿名内部类类体!
}

匿名内部类的应用主要有两种:一种是匿名类继承父类、另一种是匿名类实现接口

//匿名类继承父类

//一个定义类
class Polygon {  
   public void display() {
      System.out.println("在 Polygon 类内部。");
   }
}

class AnonymousDemo {
   public void createClass() {

      // 创建的匿名类继承了 Polygon 类
      Polygon p1 = new Polygon() {
         public void display() {
            System.out.println("在匿名类内部。");
         }
      };
      p1.display();
   }
}
//实例中,创建了 Polygon 类,该类只有一个方法 display(),AnonymousDemo 类继承了 
//Polygon 类并重写Polygon 类的 display() 方法
class Main {
   public static void main(String[] args) {
       AnonymousDemo an = new AnonymousDemo();
       an.createClass();
   }
}

上述代码中,AnonymousDemo匿名类中的createClass()方法内部继承类新建了一个Polygon对象并改写Override了display()方法,这中间的p1对象调用并销毁次数与方法调用次数一致。

//匿名类实现接口
//首先定义一个接口
interface Inter{
	void run();  //内部只有一个run()方法
}

//再定义一个实现,这是一个有名字的类,是可以反复调用新建对象的 
class Imp implements Inter{
	
	@override
	public void run(){
		System.out.println("我正在跑!");
	}
}

//然后定义public主类
public class AnonymousInnerClass{
	public void test(Inter a)
	{
		a.run();  //方法的定义
	}
	public static void main(String[] args)
	{
		AnonymousInnerClass b = new AnonymousInnerClass();  //创建对象
		//  b.test();  //!!括号内需要传参
		//一般情况下,我们可以通过implements实现接口,这里我我们采用匿名类;
		b.test(new Imp);  //可以通过定义的实现完成接口,输出结果为 我正在跑!
		
		//此外,可以通过定义匿名类来实现接口

		b.test(new Inter(){  //没有实际名字的类
			@Override
			public void run(){
				System.out.println("我正在慢跑五分钟!");
			}
		});  //定义和调用同时进行,调用结束,这个类直接被销毁
		//每一次调用,这个方法只能调用一次,每一次都是新的
	}
}

局部内部类

定义在方法内部的,作用域只限于本方法,称为局部内部类。

局部内部类的的使用主要是用来解决比较复杂的问题,想创建一个类来辅助我们的解决
方案,到那时又不希望这个类是公共可用的,所以就产生了局部内部类。局部内部类和成员
内部类一样被编译,只是它的作用域发生了改变,它只能在该方法中被使用,出了该方法就
会失效。

/**
* 测试局部内部类
*/
public class TestLocalInnerClass {
	public void show() {
		//作用域仅限于该方法
		class Inner {
			public void test() {
				System.out.println("Hello World");
			}
		}
		new Inner().test(); //调用结束就销毁
	}
	public static void main(String[ ] args) {
		new TestLocalInnerClass().show();
	}
}

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 成长之路 设计师:Amelia_0503 返回首页