【JavaSE基础】Java内部类

Java内部类

1、概念

内部类是指在一个外部类的内部再定义一个类。

2、特征
  • 1、内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号。
  • 2、内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的。
  • 3、内部类声明成静态的,就不能随便的访问外部类的成员变量了,此时内部类只能访问外部类的静态成员变量。(这与类中的静态成员方法只能访问静态成员是类似的)。
3、作用
  • 1、内部类可以很好的实现隐藏,一般的非内部类,是不允许有private和protected访问权限,但内部类可以。
  • 2、内部类拥有外围类的所有元素的访问权限。
  • 3、可以实现多重继承。
  • 4、可以避免修改接口而实现同一个类中两种同名方法的调用。
4、分类

Java内部类分为: 实例内部类、静态内部类、匿名内部类、局部内部类。

4.1、实例内部类

实例内部类,直接定义在类中。就是作为外部类的成员,可以直接使用外部类的所有成员和方法,即使是private的。同时外部类要访问内部类的所有成员变量/方法,则需要通过内部类的对象来获取。

要注意的是,实例内部类不能含有static的变量和方法。因为实例内部类需要先创建了外部类,才能创建它自己的。

实例内部类可用访问权限修饰符public,protected,friendly(默认),private。

class Car{
    class Windows{//实例内部类
        private String name;
        private int high;
    }
    private Windows windows;
    public Car(){
        windows = new Windows();
    }
}
class Outer {
    public static void main(String[] args) {
        Outer outer = new Outer();
        Outer.Inner inner = outer.new Inner(); //创建成员内部类的对象,左边的Outer可以不要
        inner.print("调用内部类的方法");
    }
    public class Inner {
        public void print(String str) {
            System.out.println(str);
        }
    }
} 
4.2、静态内部类

与实例内部类定义的唯一区别是前面加了一个static的修饰符。

静态内部类,不需要内部类对象和外部类对象之间的联系。

class A{
    static class B{ //静态内部类
        private String name;
        private int age;
        public B(){
            this.name = name;
        }
    }
    private String name;
    private int age;
    private B b;
    public A(){
        this.name = name;
        b = new B();
    }
}
class Outer {
    static class Inner{
        static class In{

        }
        public void print(String str) {
            System.out.println(str);
        }
    }
    public static void main(String[] args) {
        Outer.Inner inner = new Outer.Inner(); //创建静态内部类的对象
        inner.print("调用内部类的方法");
    }
}

静态内部类和实例内部类的区别:

  • 实例内部类不能有static数据和static属性,也不能包含静态内部类,但静态内部类可以。

  • 创建内部类对象时静态内部类必须用Outer.Inner,实例内部类可以用Outer.Inner,也可以用Inner。

  • 实例内部类和静态内部类的区别(实例内部类相比静态内部类的开销在哪里?)

    • 实例内部类包含两个this (指向当前对象,外部类对象的this)
    • 静态内部类包含一个this (指向当前对象)
  • 实例内部类,静态内部类使用上对象的生成方式:

    • 实例内部类对象:OutClass.InnerClass i = new OutClass().new InnerClass();

    • 静态内部类对象:OutClass.InnerClass i = new OutClass.InnerClass();

4.3、匿名内部类

有时候为了免去给内部类命名,便倾向于使用匿名内部类,因为它没有名字。

匿名内部类是不能加访问修饰符的。即它的访问权限修饰符只能是friendly(默认的)。

要注意的是,new 匿名内部类,这个类是要先定义的。

匿名内部类实际上就是继承一个已经存在的类,但是省略自身类的名字。

当所在的方法的形参需要被内部类里面使用时,该形参必须为final。

interface Interface {
    void show();
}
abstract class A{
    abstract void show();
}
class Test{ //匿名内部类
    public static void main(String[] args) {
        A a = new A(){
            @Override
            void show() {

            }
        };
        Interface i = new Interface() {
            @Override
            public void show() {

            }
        };
    }
}
class Outer {
    public Inner getInner(final int i,int j) {
        return new Inner(){
            int k;
            {
                k=i;//如果是k=j,会报错
            }
        };
    }
    public static void main(String[] args) {
        Outer outer = new Outer();
        Inner inner = outer.getInner(2014,11); //创建指向匿名内部类的父类对象引用
    }
    public class Inner {
        public void print(String str) {
            System.out.println(str);
        }
    }
}
4.4、局部内部类

局部内部类,是指内部类定义在方法和作用域内。

局部内部类只在该方法或条件的作用域内才能使用,退出这些作用域后无法引用的。

局部内部类可用访问权限修饰符只有friendly(默认)。

定义在方法内:

class Outer {
    public In play(){
        class Inner extends In{
            public void print(String str) {
                System.out.println(str);
            }
        }
        return new Inner();
    }
    public static void main(String[] args) {
        Outer outer = new Outer();
        In inner = outer.play(); //创建指向局部内部类的基类对象引用,只有这样才可以在局部内部类的作用于外使用局部内部类
        inner.print("调用内部类的方法");
    }
}
class In{
    public void print(String str) {
    }
}

定义在作用域里:

class Outer {
    public In play(int i){
        if(i>5){
            class Inner extends In{
                public void print(String str) {
                    System.out.println(str);
                }
            }
            return new Inner();
        }
        return null;
    }
    public static void main(String[] args) {
        Outer outer = new Outer();
        In inner = outer.play(2014); //创建指向局部内部类的基类对象引用,只有这样才可以在局部内部类的作用于外使用局部内部类
        inner.print("调用内部类的方法");
    }
}
class In{
    public void print(String str) {
    }
}
5、访问修饰符
5.1、修饰成员

public、默认、protected、private -> 修饰成员

protected <=> 默认 包访问权限

继承:子类和父类定义在不同包下,子类可以访问父类用protected修饰的属性和方法

5.2、修饰类:

修饰外部类:public 默认

修饰内部类:四种访问修饰符都行

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值