java内部类

本文详细解析了Java内部类的概念,包括成员内部类、局部内部类、静态内部类和匿名内部类的特点及应用场景,探讨了内部类如何实现多重继承,以及它们在编程中的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

内部类:可以将一个类的定义放在另一个类的定义内部。

一、成员内部类

作为外部类的成员存在,与成员变量和成员方法平级关系。

1.1 声明

public class Out{
    //成员变量
    //成员方法
    //成员内部类
    访问权限 class In{
        //成员变量
        //成员方法
    }
}

1.2 说明

1.2.1 语法说明

访问权限是任意的,内部类是属于外围类,就是为了更好控制,所以一般不用public.

1.2.2 如何创建成员内部类的对象

由于成员内部类作为外部类的成员存在,若想访问类成员需要通过对象,所以成员内部类对象需要通过外部类对象创建。
语法:
//创建外部类对象
Out o = new Out();
//通过外部类找到内部类,通过外部类对象创建内部类对象
Out.In i = o.new In();

1.2.3 如何在成员内部类中访问外部类的成员
i.当外部类的属性和内部类属性不同名时,可以直接访问
ii.当外部类属性与内部类属性同名时,格式:
    外部类名.this.属性名(通过这个格式在内部类中访问外部类的同名属性)
1.2.4 成员内部类编译后字节码保存的文件格式

外围类:Outer.class 成员内部类:Outer$Inner.class

1.3 简单实现

public class Outer {
    public  int num = 10;//成员变量
    //成员方法
    void show1() {
        System.out.println("成员方法show"+num);
    }
    //成员内部类 访问权限任意
    class Inner {
        public int num = 20;//成员内部类的成员变量
        //成员内部类的成员方法
        public void show() {
              int num = 30;
              System.out.println(num);
             System.out.println(Inner.this.num);
             //当内部方法中类访问外部类成员变量时  外围类.this.变量名
             System.out.println(Outer.this.num);
        }
    }
    public static void main(String[] args) {
        //内部类作为外围类的成员变量存在,成员内部类的对象需要外围类对象创建
        Outer outer = new Outer();
        outer.show1();
        Outer.Inner inner = outer.new Inner();
        inner.show();
    }
}

二、局部内部类

作为局部成员存在,和局部变量平级。

2.1 声明

public class Outer{
    //成员变量
    //成员方法
    //局部内部类所在的方法
    public void show(){
        //功能代码
        //局部内部类
        访问权限 class Inner{
            //局部内部类的成员变量
            //局部内部类的成员方法
        }
    }
}

2.2 说明

局部内部类的访问权限:只能是默认

2.2.1 如何创建局部内部类对象

直接在局部内部类所在的方法中创建对象并调用方法

2.2.2 如何在局部内部类中访问外部类的属性:
i.不同名,直接访问
ii.同名,外部类名.this.属性名
2.2.3 字节码文件:
外部类名$编号内部类名.class
![这里写图片描述](https://img-blog.youkuaiyun.com/20180731104434481?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3ODIyMjM0/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

2.3 简单实现

public class Outer {
    int num = 10;// 成员变量
    // 成员方法

    void show1() {
        class In { } // 成员方法中定义一个类,局部内部类
        System.out.println("外围类成员方法show" + num);
    }
    //局部内部类所在的方法
    public void show() {
        //public class In{} 
       class In{} //局部内部类只能是默认权限
       class Inner {
              int num = 30;
              void display() {
                  int num =20;
                  System.out.println(num);
                  System.out.println(Inner.this.num);
                  System.out.println(Outer.this.num);
                  System.out.println("局部内部类的display方法");
              }
       }
       //直接在局部内部类所在的方法中创建对象并调用方法
       Inner i= new Inner();
       i.display();
    }
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.show1();
        //局部内部类具有作用域,所以调用外部类对象的fun3方法时
        //会声明局部内部类并创建对象调用方法
        outer.show();
    }
}

三、静态内部类

static修饰的外围类的成员内部类,只能是成员内部类。

3.1 声明

public class Out{   
    访问权限 static class In{
    }
}

3.2 说明

访问权限:任意的,一般使用public
使用static修饰的成员内部类,自动提升为普通类,相当于一个独立的类,所有创建对象时不需要外围内对象。

3.2.1 创建对象:

不需要外部类的对象,可以直接创建静态内部类的对象
格式:内部类 标识符 = new 内部类构造方法

3.2.2 访问外部类的成员

只能直接访问外部类的静态成员
非静态的成员只能通过创建外部类对象访问

3.2.3 字节码文件格式:
外部类名$内部类名.class(与成员内部类一样)
Outer$Inner.class

3.3 简单实现

//static可以修饰类成员(属性,方法,块,成员内部类)
public class Outer {
    public  int num = 10;//成员变量
    //成员方法
    void show() {
        System.out.println("外围类成员方法show"+num);
    }
    //静态内部类 访问权限任意,一般使用public
    //使用static修饰的成员内部类,自动提升为普通类,相当于一个独立的类
    public static class Inner {
        public int num = 20;//静态内部类的成员变量
        static String name ="Tom";
        //静态内部类的成员方法
        public void show() {
              int num = 30;
              System.out.println(num);
             System.out.println(Inner.this.num);
             //静态内部类里不能直接方法外围类非静态成员
             //System.out.println(Outer.this.num);
           //非静态的成员只能通过创建外部类对象访问
             Outer o = new Outer();
             System.out.println(o.num);
             //只能直接访问外部类的静态成员
             System.out.println(name);
             System.out.println("static内部类的show方法");
        }
    }
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.show();
        //不需要外部类的对象,可以直接创建静态内部类的对象
        Inner inner = new Inner();
        inner.show();
    }
}

四、匿名内部类

4.1 说明

什么是匿名内部类: 没有名字的内部类
原理产生原因:

由于接口和抽象类不能创建对象,若一个接口的实现类只需要使用一次,或一个抽象类的非抽象类只需要使用一次,可以使用匿名内部类,匿名内部类只能创建一个对象

4.2 简单实现

public interface InterF {
    void show();
}
public class Outer {
    public static void main(String[] args) {
        new InterF() {

            @Override //重写抽象方法
            public void show() {
                System.out.println("重写匿名内部类show方法");
            }
            //匿名内部类中可以声明独有的属性和方法,但是由于接口引用不能
            //访问实现类中独有的属性和方法,所以一般不在匿名内部类中声明独有的方法
            public void display() {
                System.out.println("独有的方法");
            }
        }.show();;
    }
}

4.3匿名类编译后字节码文件格式

InterF.class
Outer$1.class
Outer.class

测试类$编号.class
匿名内部类只能使用一次,即便两次声明的匿名内部类完全一致,也是两个匿名内部类

4.4 匿名类的注意事项

匿名内部类中必须把抽象方法全部实现
匿名内部类中可以声明独有的属性和方法,但是由于接口引用不能访问实现类中独有的属性和方法,所以一般不在匿名内部类中声明独有的方法
匿名对象:若在匿名内部类中声明了独有的方法和属性,可以使用匿名对象访问,匿名对象只能使用一次

五、内部类的好处

每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类是没有影响的。

如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方法得以变得完整。接口解决了部分问题,内部类有效的实现了“多重继承”,也就是说内部类允许继承多个类或抽象类。
考虑以下的一种情况:在一个类中实现两个接口。一是用单一类,而是用内部类。

public interface A {
    void show();
}
public interface B {
    void fun();
}
//单一类实现A,B两个接口
public class ABImp implements A ,B{
    public void show() {
        System.out.println("show()--A");
    }
    public void fun() {
        System.out.println("fun()--B");
    }
}
//使用内部类
public class BInner implements A {
    public void show() {
        System.out.println("BInner_show");
    }
    B makeB() {
        return new B() {
            @Override
            public void fun() {
                System.out.println("BInner_fun");
            }};
    }

}
//测试类
public class Test {
    public static void main(String[] args) {
        ABImp abImp  = new ABImp();
        abImp.show();
        abImp.fun();

        BInner bInner = new BInner();
        bInner.show();
        bInner.makeB().fun();
    }
}

以上两种方式从实现的较大看没有什么区别。但是这两种方式都有一定的逻辑意义,当遇到问题的时候通常问题本身就会给出某些指引,告诉你应该怎样使用。
上面面向的是接口,那如果拥有的是类或者抽象类,那就只能使用内部类实现多重继承。

//普通具体类
public class D {
    void run() {
        System.out.println("D-run");
    }
}
//抽象类
public abstract class E {
    abstract void play() ;
}
//内部类实现多重继承
public class Z extends E {
    void play() {
        System.out.println("Z_E_play");
    }
    D makeD() {
        return new D() {};
    }
}

内部类的特性
1、内部类是一种非常有用的特性,它允许你把一些逻辑相关的类组织在一起,并控制位于内部的类的可视性。看起来就像是一种代码隐藏机制:将类置于其他类的内部。
2、内部类可以拥有多个实例,每个实例都有自己的状态信息,并且与其外围类对象的信息相互独立。
3、在单个外围类中,可以让多个内部类以不同的方式实现同一个接口或继承同一个类。
4、内部类没有“is-a”关系,它是独立的实体。
5、静态内部类(嵌套类)不需要对外围类对象的依赖即可创建对象,还可以定义static变量或方法。但是局部、成员、匿名内部类不能定义静态的成员,成员内部类对象的创建需要依赖外围类对象的引用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值