Java面向对象—内部类

什么是内部类

在Java中,允许在一个类的内部定义类,这样的类称作内部类。如:

在实际情况中,根据内部类的位置、修饰符和定义方式的不同,内部类可以分为4种形式:成员内部类、局部内部类、静态内部类、匿名内部类。

1.成员内部类

成员内部类:内部类的位置与成员变量、成员方法相同。是外部类中的一个成员。

我们先来定义一个包含成员内部类的类:

class Outer{
    int m = 0;
    void text1(){
        System.out.println("外部类成员方法");
    }
    class Inner{
        int n = 1;
        void show1(){
            System.out.println("内部类成员方法,外部成员变量m="+m);
        }
    }
    void text2(){
    	Inner i = new Inner();
    	System.out.println("外部类成员方法,内部类成员变量n="+i.n);
    }
    
}

下面来定义一个测试类:

public class Text {

	public static void main(String[] args) {
		Outer o = new Outer();
		Outer.Inner i = o.new Inner();
		i.show1();
		o.text2();
	}

}

注意成员内部类对象的定义方法

外部类名.内部类名 变量名 = new 外部类名().new 内部类名();

 我们来看一下运行结果

 通过运行结果可以看出,成员内部类可以访问外部类的所有成员,同时外部类也可以访问成员内部类的所有成员。

2.局部内部类

局部内部类:也叫方法内部类,就是定义在某个局部范围中的类,它和局部变量一样,都是在方法中定义的,其有效范围也智局限在方法的内部。

我们先来定义一个包含局部内部类的类

public class Outer {
	int m = 0;
	void text1(){
		System.out.println("外部类成员方法");
	}
	void text2(){
		class Inner{
			int n = 1;
			void show(){
				System.out.println("内部类成员方法,外部类变量m="+m);
			}
		}
		Inner i = new Inner();
		i.show();
	}
}

 在测试类中,仅定义一个外部类对象即可,用外部类对象来调用包含内部类的方法,即可实现内部类中的成员变量和成员方法。

 运行成功,局部内部类成功调用了外部类中的变量

我们在外部类的其他方法中,创建内部类对象来调用show方法

这时编译器报错。 说明text2方法的外部不能定义内部类对象

局部内部类可以访问外部类的所有成员,但只在包含内部类的成员方法中,才可以访问内部类的所有成员。

3.静态内部类 

 静态内部类:静态内部类很简单,就是被static修饰的成员内部类

我们将上面的局部内部类稍作修改,把内部类的前面用 static 修饰。

 这时我们发现,代码的第11行报错了。因为静态内部类只能访问外部类中被static修饰的变量

将变量int m也用static修饰

 编译器不再报错

写一个测试类来测试一下运行结果

 运行成功,调用了外部类中的静态成员。

静态内部类在创建内部类对象时,可直接跳过外部类对象

外部类名.静态内部类名 变量名 = new 外部类名.静态内部类名();

4.匿名内部类 

匿名内部类:匿名内部类是局部内部类的一种。

格式:

new 类名或接口名(){

  //匿名内部类

};

 本质:

匿名内部类以new开头,其本质是一个继承了该类或实现了该接口的子类匿名对象。

下面我们就用代码来演示:

匿名内部类是一个继承了父类或实现了接口的子类匿名对象,那么我们就要先来定义一个父类或接口。我们在这里来定义一个接口,在接口中定义一个show方法

public interface Inter {
	void show();
}

匿名内部类是局部内部类的一种,那么就要在成员方法内部来写成员内部类。我们来定义一个外部类,在外部类的成员方法中,定义匿名内部类。

public class Outer {
	public void text(){
		new Inter(){
			@Override
			public void show(){
				System.out.println("匿名内部类重写的show方法");
			}
		};
	}
}

我们再来写一个测试类,调用外部类中的Text方法,看看匿名内部类中的show方法会不会运行。

 结果直接输出 运行结束,并没有调用匿名内部类中的show方法。

这是为什么呢?匿名内部类的本质是一个匿名对象,是一个没有名字的对象。我们在text方法中定义了一个匿名内部类,却并没有去调用它里面的show方法。

问题又来了,既然匿名内部类是一个没有名字的对象,那么我们就无法通过 对象名.方法名 的方式来调用匿名内部类中的方法。那我们应当如何来调用匿名内部类中的方法呢?这还要回到匿名内部类的本质,它是一个对象。那么我们是否可以通过 对象.方法名 ,来调用对象中的方法。我们来试验一下。

在匿名内部类的花括号外,紧跟一个.show();

 编译器并没有报错,我们回到测试类中,不做任何修改,测试一下

 show方法成功运行。

当然,我们也可以声明一个对象名,将对象赋值给它,在通过方法名调用方法,这样也是可以的。

 内部类在开发中的应用是怎样的呢?

我们用代码来演示

public class Animal {
	public void eat(InterEat i){
		i.eat();
	}
}
public interface InterEat {
	void eat();
}

定义一个Animal类,Animal中有一个eat方法,eat方法需要传入一个接口类型的对象。我们要在Demo类中调用这个eat方法。根据我们之前学过的知识,要先创建一个接口实现类,实现接口

public class Cat implements InterEat{
    @Override
	public void eat(){
		System.out.println("猫吃鱼");
	}
}

在Dome类中创建实现类对象,即可调用eat方法。

 如果我还想加一个狗的eat方法,那么就要创建一个狗类,让狗类实现接口类,再在Dome类中创建一个狗类对象,再将狗类对象的参数传入Animal类中的eat方法。这样做太麻烦。我们就可以用匿名内部类来简化

public class Dome {
	public static void main(String[] args) {
		Animal a = new Animal();
		a.eat(new InterEat(){
			@Override
			public void eat(){
				System.out.println("猫吃鱼");
			}
		});
	}
}

运行成功 

我们直接给eat方法传入一个匿名内部类。把匿名内部类放入到括号中。这样一来,我们就可以直接省去创建类、创建类的对象、传参的过程。

如果我们还想运行一个狗的eat方法,我们不需要再创建狗类,直接给eat方法传入一个内部类即可。

运行成功 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

G.E.N.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值