1.内部类的基本概念
内部类就是在一个类的内部定义的类
成员内部类定义如下:
class Outer{
class Inner{}
}
编译以后会产生两个文件
Outer.class Outer$Inner.class
2.在外部创建内部类的对象
内部类除了可以在外部类中产生实例化对象,也可以在外部类的外部来实例化。那么,根据内部类生成的*.class文件:Outer$Inner.class , “$”符号在程序的运行时将被替换成“.”所以内部类的访问:通过“外部类.内部类”的形式表示。
//产生外部类的实例
Outer out = new Outer();
//声明内部类对象
Outer.Inner in = null;
//实例化内部类对象
in = out.new Inner();
成员内部类的Demo:
public class InnerClassDemo1 {
public static void main(String args[])
{
Dog d = new Dog("花花");
d.say();
//声明内部类的引用
Dog.ChildDog child = null;
//创建内部类的实例,但是该方法一般不使用
child = d.new ChildDog();
child.talk();
//比较常用的方法
d.childTalk();
}
}
//狗类
class Dog{
private String name;
public Dog(String name)
{
this.name=name;
}
public void say()
{
System.out.println("我是一只狗,主人叫我"+name);
}
//内部类(成员内部类)
class ChildDog{
public void talk(){
//内部类可以直接使用外部类的属性
System.out.println("我是一只狗,我妈是"+name);
}
}
//直接在外部类的内部定义方法
public void childTalk()
{
ChildDog child = new ChildDog();
child.talk();
}
}
3.方法内部类
内部类可以作为一个类的成员外,还可以把类放在方法内定义
格式:
class Outer
{
public void doSomething()
{
class Inner{
public void seeOuter(){}
}
}
}
注意
(1)方法内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化
(2)方法内部类对象不能使用该内部类所在方法的非final局部变量
public class InnerClassDemo2 {
public static void main(String args[])
{
Dog1 d = new Dog1("花花");
d.childTalk();
}
}
class Dog1{
private String name;
public Dog1(String name)
{
this.name=name;
}
public void say()
{
System.out.println("我是一只狗,主人叫我"+name);
}
//在方法里面声明一个内部类
public void childTalk()
{
class ChildDog1{
public void talk()
{
System.out.println("我是一只狗狗,我妈妈是"+name);
}
}
//只能在这里进行实例化,因为涉及到作用域
ChildDog1 childDog1 = new ChildDog1();
childDog1.talk();
}
}
4.静态内部类
在一个类内部定义一个静态内部类,静态的含义是该内部类可以像其他静态成员一样,没有外部类对象时,也能够访问它。静态嵌套类仅能访问外部类的静态成员和方法。
public class InnerClassDemo3 {
public static void main(String args[])
{
//注意静态内部类与成员内部类在声明实例化对象时的区别
Dog.ChildDog child = new Dog.ChildDog();
child.talk();
Dog.childTalk();
}
}
class Dog{
static private String name;
public Dog(String name)
{
this.name=name;
}
public void say()
{
System.out.println("我是一只狗,主人叫我"+name);
}
//静态内部类
static class ChildDog{
public void talk()
{
//静态内部类只能访问外部类中的静态成员和方法
System.out.println("我是一只狗狗");
}
}
public static void childTalk()
{
ChildDog c = new ChildDog();
c.talk();
}
}
5.匿名内部类
没有名字的内部类
匿名内部类的三种情况
(1)继承式的匿名内部类
(2)接口式的匿名内部类
(3)参数式的匿名内部类
public class InnerClassDemo4 {
public static void main(String args[])
{
//1.继承式匿名内部类,{}表示实现1个子类
Dog1 dog1 = new Dog1("小白"){
public void say()
{
System.out.println("我是一只母狗,主人叫我"+name);
}
};
dog1.say();
//2.接口式的匿名内部类,{}中是接口的实现
Child child = new Child() {
@Override
public void talk() {
System.out.println("我是一只小狗狗");
}
};
child.talk();
//3.参数式的匿名内部类
childTalk(new Child() {
@Override
public void talk() {
System.out.println("我是一只小狗狗");
}
});
}
public static void childTalk(Child c){
c.talk();
}
}
class Dog1
{
protected String name;
public Dog1(String name){
this.name=name;
}
public void say()
{
System.out.println("我是一只狗,主人叫我"+name);
}
}
interface Child{
public void talk();
}
匿名内部类省去了去单独实现一个接口或者继承一个来创造实例的麻烦,直接在实例化的同时实现相应的内部类。
6内部类的作用
每个内部类都能独立地继承自一个(接口的)实现,所以无论外部类是否已经继承了某个接口的实现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或者抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得更完整。接口解决了部分问题,而内部类有效地的实现了“多重继承”