详述有名内部类与匿名内部类

在一个外部类中定义的类称为内部类,内部类按照有无名字可以划分为有名内部类和匿名内部类

一.有名内部类

有名内部类顾名思义就是有名字的类,如下就是一个有名内部类,内部类中可以像正常的类一样定义属性和方法:

public class Body {

	class Heart{
		void work(){
			System.out.println("working");
		}
	}
}

二.匿名内部类

匿名内部类天生没有类名,但是创建对象却需要类名,所以解决办法就是在匿名内部类定义的时候和创建对象一起定义,而创建对象使用父类的构造方法,如果父类是接口则使用new(接口名)()的方式创建对象,如下:

public class Mammal {

	void work() {
		System.out.println("...");
	}
}


public class Body {

	Mammal mammal=new Mammal() {//匿名内部类
		
	};
}

对于这个创建和定义的方式,存在着好多的疑点,在下面会一一解答。

三.匿名内部类的特点

1.匿名内部类是普通类的子类

在匿名内部类的定义过程中,使用的是父类的构造方法,而所有普通类都可以作为匿名内部类的父类,上一段代码中就是使用的普通类

2.匿名内部类是抽象类的子类

当我们将Mammal类改为抽象类,在创建匿名内部类时还是可以使用Mammal类的构造方法,所以抽象类也可以作为匿名内部类的父类。

public abstract class Mammal {

	void work() {
		System.out.println("...");
	}
}


public class Body {

	Mammal mammal=new Mammal() {
		
	};

}

3.匿名内部类是接口的实现类

如果将Mammal定义为接口,则匿名内部类则是接口的实现类,在创建对象时还是一样的操作,还可以在内部类中重写接口中的方法进行实现:

public interface Mammal {

	void work();
}


public class Body {

	Mammal mammal=new Mammal() {

		@Override
		public void work() {
			System.out.println("working...");
		}
	};
}

4.匿名内部类不能为抽象类

因为匿名没有名字,如果可以抽象,则该匿名类必须有子类,但是由于没有名字,无法被继承,所以没有子类

5.匿名内部类的创建是对象上转型

它的原理就是将匿名内部类的对象的地址存放在了Mammal类的变量mammal中,所以用对象mammal调用work方法时,表面上调用Mammal中的work方法,实则调用匿名内部类中的work方法:

public class Mammal {

	void work() {
		System.out.println("work");
	}
}


public class Body {

	public static void main(String[] args) {
		Mammal mammal=new Mammal() {

			@Override
			public void work() {
				System.out.println("working...");
			}
		};
		mammal.work();
	}
}

6.匿名内部类新增的属性和方法

匿名内部类中可以新增属性和方法,但是因为匿名内部类创建的是上转型对象,而上转型对象调无法调用新增的属性和方法。

7.匿名内部类不能自定义构造方法

因为匿名内部类没有名字,所以根本就无法使用构造方法,自然也不能定义构造方法,只能通过调用父类的构造方法来创建对象

四.内部类的使用

1.编译方式

无论是有名内部类还是匿名内部类,javac都会产生一个独立的class文件,编译之后内部类会被编译成独立的.class文件。

如果该内部类为有名内部类,则有名内部类字节码文件名为外部类的类名+$+内部类类名;

如果为匿名内部类,则匿名内部类字节码文件名为外部类类名+$+数字;

去到存储项目的文件中即可查到编译生成的class文件

2.final修饰符

如果要在内部类中使用局部变量的值,需要在前面加final,如果JDK是8.0及以上版本的则不需要加:

public class Body{

	public static void main(String[] args) {
		Mammal mammal=new Mammal() {

			public void work(final String name) {
				System.out.println(name);
			}
		};
	}
}

3.private修饰的成员变量

如果一个成员变量被private修饰,则说明该成员变量只能在本类中使用,而内部类就是定义在外部类中,所以该成员变量可以在内部类中使用

public class Body{

	private static int age=12;
	public static void main(String[] args) {
		Mammal mammal=new Mammal() {

			public void work() {
				System.out.println(age);
			}
		};
		mammal.work();
	}
}

4.访问权限

能修饰类的访问权限修饰符有public和默认的,但是在直接定义在外部类中的内部类,public、默认的、protected、private都可以修饰它:

public class Body{

	protected Mammal mammal=new Mammal() {

		public void work() {
			System.out.println();
		}
	};
}

5.内部类的调用

我们都知道,在静态方法中无法调用非静态方法,那么如果一个内部类是非静态的,且直接定义在类中,则不能直接在main方法中创建对象,要先创建外部类的对象,然后用外部类调用构造方法创建内部类对象,再通过内部类对象调用内部类中的方法:

public class Body{

	class Heart{
		
		public void work() {
			System.out.println("working");
		}
	}
	
	public static void main(String[] args) {
		Body body = new Body();
		Heart heart=body.new Heart();
		heart.work();
	}
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值