黑马程序员技术交流社区

标题: 【成都校区】快速提高对内部类的理解 [打印本页]

作者: 小刀葛小伦    时间: 2020-3-20 14:41
标题: 【成都校区】快速提高对内部类的理解
内部类
什么是内部类?简单点就是面向对象程序设计的概念。面向对象程序设计中,是可以在一个类的内部定义另外一个类,这种类统称为嵌套类,它有两种类型,即静态嵌套类和非静态嵌套类。静态嵌套类使用的频率很少,基本用不到,最重要的还是非静态嵌套类,也被称作为内部类(inner)。内部类是JAVA语言的主要附加部分。内部类几乎可以处于一个类内部任何位置,可以与实例变量处于同一级,或处于方法之内,甚至是一个表达式的一部分。

如果一个类存在的意义就是为指定的另一个类,可以把这个类放入另一个类的内部。就是把类定义在类的内部的情况就可以形成内部类的形式。A类中又定义了B类,B类就是内部类。B类可以当做A类的一个成员看待。

内部类我们从外面看是非常容易理解的,无非就是在一个类的内部在定义一个类。

首先来说一下内部类的三种定义形式:
1、在一个类(外部类)中直接 定义的内部类;
2、在一个方法(外部类的方法)中 定义的内部类;
3、匿名内部类。

内部类的特点:
1、 内部类可以直接访问外部类中的成员,包括私有成员
2、 外部类要访问内部类的成员,必须要建立内部类的对象
3、 在成员位置的内部类是成员内部类
4、 在局部位置的内部类是局部内部类

成员内部类被private修饰

成员内部类也是最普通的内部类,它是外围类的一个成员,所以他是可以无限制的访问外围类的所有 成员属性和方法,尽管是private的,但是外围类要访问内部类的成员属性和方法则需要通过内部类实例来访问。
public class InnerClass2 {
    public static void main(String[] args) {
       //创建内部类对象,并执行show()

        /* -- Outer2.Inner2 oi = new Outer2().new Inner2();
         * -- 报错,Inner2已经被private了
         */

       //3,测试被private的内部类的资源能否执行!
       new Outer2().test();
    }
}

class Outer2{
    //2,如果想要访问private的内部类,可以访问外部类提供的对应方法
    public void test() {
       //访问内部类方法
      new Inner2().show();
    }   

    //位置在类里方法外--成员内部类
    //1,内部类可以被private修饰,但是外界无法直接创建对象了!
    private class Inner2{
       public void show() {
           System.out.println("Inner2.show()");
       }
    }
}

被static修饰的内称为静态内部类,不过我们更喜欢称之为嵌套内部类。静态内部类与非静态内部类之间存在一个最大的区别,我们知道非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围内,但是静态内部类却没有。

它的创建是不需要依赖于外围类的。

它不能使用任何外围类的非static成员变量和方法。

public class InnerClass3 {
    public static void main(String[] args) {
       // 创建内部类对象测试show()

        /* -- Outer3.Inner3 oi = new Outer3().new Inner3();
         * -- 报错,原因是Inner3是静态的内部类
         */
           Outer3.Inner3 oi = new Outer3.Inner3();//Outer3.Inner3通过类名.调用类中的静态资源
       oi.show();   
       Outer3.Inner3.show2();//调用静态内部类里的静态方法
    }
}

class Outer3{   
    //1,内部类被static修饰--随着类的加载而加载,会造成内存资源浪费,并不常用!
    static class Inner3{
       public void show() {
           System.out.println("Inner3.show()");
       }
       static public void show2() {
           System.out.println("Inner3.show2()");
       }
    }
}

局部内部类:有这样一种内部类,它是嵌套在方法和作用于内的,对于这个类的使用主要是应用与解决比较复杂的问题,想创建一个类来辅助我们的解决方案,到那时又不希望这个类是公共可用的,所以就产生了局部内部类,局部内部类和成员内部类一样被编译,只是它的作用域发生了改变,它只能在该方法和属性中被使用,出了该方法和属性就会失效。

匿名内部类属于局部内部类,并且是没有名字的内部类。

public class InnerClass5 {
    public static void main(String[] args) {
       new Hello() {// 匿名对象,本身接口不能new,这里new Hello()匿名对象,就相当于Hello接口的实现类
           // 匿名内部类
           @Override
           public void save() {
           System.out.println("save()..");
           }
           @Override
           public void update() {
              System.out.println("update()..");
           }
       }.update();// 触发指定的方法
       new Hello2() {//抽象类的匿名内部类
           @Override
           public void show() {  }
       }.show();      
       new Animal() {//普通类的匿名内部类
           @Override
           public void eat() {   }
       };
    }
}

//创建匿名对象+匿名内部类测试
class Animal{
    public void eat() {}
}

abstract class Hello2 {
    abstract public void show();
    public void delete() {   }
}

// 定义接口
interface Hello {
    void save();
    void update();
}

观察上面的代码,我们看清几个地方:
         -- 匿名内部类是没有访问修饰符的。
     -- new 匿名内部类,这个类首先是要存在的。如果我们将那个InnerClass接口注释掉,就会出现编译出错。
     -- 匿名内部类是没有构造方法的。因为它连名字都没有何来构造方法。

总结:我们为什么要使用内部类呢?看过《Think in java》的应该都知道,其中有这样一句话:“Java在程序设计中使用内部类最吸引人的原因是:每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。”甚至可以这样说,接口只是解决了部分问题,而内部类使得多重继承的方法方式使解决方案变得更加完整。







欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2