文章类容选自尚硅谷,jdk8,eclipse环境。
内部类的特性
内部类是创建在类内的类,它有类内成员和类的两方面的属性
内部类可以分为成员内部类和局部内部类
- 成员内部类作为类的成员,就像类的属性一样,可用static关键字修饰
- 局部内部类可以放在构造器,方法和代码块内,就像类的局部变量一样
从属性来讲,一方面,它作为类内的成员
- 可以被static关键字修饰,就像static关键字修饰属性一样
- 被static关键字修饰内部类,只能是成员内部类,不能是局部内部类。
- 可以调用外部类的方法和属性
- 可以使用4种权限修饰符
另一方面,它作为一个类
- 可以被abstract关键字修饰,意味着它不可以实例化
- 可以被final关键字修饰,意味着它不可以被继承
- 类内可以定义属性,方法,构造器
- 内部类内还可以嵌套内部类,只不过很少见
示例代码如下
package com.atguigu.java2;
public class InnerClassTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
class Person{
public void eat(){
System.out.println("人吃饭");
}
//成员内部类,可被static关键字修饰,也可以被abstract关键字修饰
static abstract class Dog{
String name;
int age;
public void show(){
System.out.println("dog shout");
}
}
final class Bird{
String name;
public Bird(){
}
public void sing(){
System.out.println("bird sing");
eat();
}
}
public void method(){
//局部内部类,可以被abstract,final关键字修饰
abstract class AA{
}
final class BB{
}
}
//局部内部类可以放到代码块内部
{
class CC{
}
}
}
以上的写法是完全合法的。
内部类调用外部类
在Bird内部类的sing方法中,调用了外部类的eat方法,实际上该eat方法是省略掉了Person.this.的关键字的。
若只加上一个this关键字,编译器会默认在内部类中找eat方法,找不到则报错,加上Person.this.的关键字,编译器则会在外部类中找eat方法
public void sing(){
System.out.println("bird sing");
eat();
Person.this.eat();
}
这两个eat方法是等价的,都调用的是外部类的eat()方法。
内部类的使用
首先分别去掉Dog类前的abstract关键字和Bird类前的final关键字,在main方法中写入测试语句。
public static void main(String[] args) {
Person.Dog dog = new Person.Dog();
dog.show();
Person p = new Person();
Person.Bird bird = p.new Bird();
bird.sing();
}
运行结果为
dog shout
bird sing
人吃饭
人吃饭
分析代码
Dog类是静态的成员内部类,在创建Dog类的时候,由于Dog类被static关键字所修饰,所以使用的时候不用先创建Person类的对象,直接通过Person.Dog就可以创建对象了。
然而在创建Bird类的时候,由于Bird类没有加static关键字修饰,在创建对象的时候必须先创建外部类的对象,然后再创建内部类的对象,注意,在创建内部类的对象的时候
Person.Bird bird = p.new Bird();
形式为 外部类对象名.new 内部类构造器 这样的形式。
外部类和内部内重名属性(方法)的调用
当外部类和内部类有重名属性的时候,可以通过关键字加以区分。
之前讲到的eat()方法,由于没有重名的情况出现,内部类在调用外部类eat()方法的时候,直接是省略掉了Person.this关键字,但是如果有重名的情况。
比如说给Person类赋上String name的属性并显式初始化为”Reiner“,给Bird类的name属性显式初始化为“dujuan”
class Person{
String name = "Reiner";
public void eat(){
System.out.println("人吃饭");
}
//成员内部类,可被static关键字修饰,也可以被abstract关键字修饰
static class Dog{
String name;
int age;
public void show(){
System.out.println("dog shout");
}
}
class Bird{
String name = "dujuan";
public Bird(){
}
public void sing(){
System.out.println("bird sing");
eat();
Person.this.eat();
}
public void displat(String name){
System.out.println(name);//输出的是方法的形参
System.out.println(this.name);//输出的是内部类的属性
System.out.println(Person.this.name);//输出的是外部类的属性
}
}
}
再在main方法中进行测试
public static void main(String[] args) {
Person p = new Person();
Person.Bird bird = p.new Bird();
bird.displat("huangli");
}
测试结果为
huangli
dujuan
Reiner
可见,通过this关键字和Person.this关键字,就区分出了内部类和外部类的属性
同类,也可以通过this关键字和外部类名.this 关键字区分出内部类和外部类的方法
用局部内部类实现接口
示例代码如下,用局部内部类实现接口
package com.atguigu.java2;
public class InnerClassTest1 {
//返回一个实现了Comparable接口的非匿名实现类的匿名对象
public Comparable getComparable(){
class MyComparable implements Comparable{
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
return 0;
}
}
return new MyComparable();
//也可以返回一个匿名实现类的匿名对象
// return new Comparable(){
//
// @Override
// public int compareTo(Object o) {
// // TODO Auto-generated method stub
// return 0;
// }
//
// }
}
}