资讯专栏INFORMATION COLUMN

Java内部类(Inner Class)小记

jackzou / 1280人阅读

摘要:要注意的是,成员内部类不能含有的变量和方法。匿名内部类是唯一一种没有构造器的类。静态嵌套类又叫静态局部类嵌套内部类,就是修饰为的内部类。以上是对内部类的一些学习和总结,纰漏之处希望各位小伙伴友情指点,共同进步。

内部类(inner class)是定义在另一个类中的类,类名不需要和文件夹相同。但为什么要使用内部类呢?其主要原因有以下三点:
  1.内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据。
  2.内部类可以对同一个包中的其他类隐藏起来。
  3.当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷。
内部类可以分为以下几种:成员内部类、局部内部类、匿名内部类和静态嵌套类。

1.成员内部类

成员内部类是最普通的内部类,它的定义为位于另一个类的内部,形如下面的形式:

class Outter {
    private int age = 12;
    class Inner {
        private int age = 13;
        public void print() {
            int age = 14;
            System.out.println("局部变量:" + age);
            System.out.println("内部类变量:" + this.age);
            System.out.println("外部类变量:" + Out.this.age);
        }
    }
}
public class test {
    public static void main(String[] args) {
        Outter out = new Outter();
        Outter.Inner in = out.new Inner();
        in.print();
    }
}

运行结果如下:

局部变量:14
内部类变量:13
外部类变量:12

从本例可以看出:成员内部类,就是作为外部类的成员,可以直接使用外部类的所有成员和方法, 即使是private的 。虽然成员内部类可以无条件地访问外部类的成员,而外部类想访问成员内部类的成员却不是这么随心所欲了。在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问:

class Outter {
    private int age = 12;
    public Outter(int age) {
        this.age = age;
        getInInstance().print();   //必须先创建成员内部类的对象,再进行访问!
    }
    private Inner getInInstance() {
        return new Inner();
    } 
    class Inner {
        public void print() {
            System.out.println("内部类没同名,所以直接调用外部类成员变量:" + age);
        }
    }
}
public class test {
    public static void main(String[] args) {
        Outter out = new Outter(10);
    }
}

运行结果:

内部类没有同名,所以直接调用外部类成员变量:10
内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限。
比如上面的例子,如果成员内部类Inner用private修饰,则只能在外部类的内部访问,如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。
这一点和外部类有一点不一样, 外部类只能被public和包访问两种权限修饰 。
由于成员内部类看起来像是外部类的一个成员,所以可以像类的成员一样拥有多种权限修饰。要注意的是,成员内部类不能含有static的变量和方法。因为成员内部类需要先创建了外部类,才能创建它自己的。

2.局部内部类

局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。

定义在方法里的内部类:

class Outter {
    private int age = 12;
        public void Print(final int x) {    //这里局部变量x必须设置为final类型!
            class Inner {
                public void inPrint() {
                    System.out.println(x);
                    System.out.println(age);
                }
            }
            new Inner().inPrint();
        }
}
public class test {
    public static void main(String[] args) {
        Outter out = new Outter();
        out.Print(10);
    }
}

运行结果:

10
12

本例中我们将内部类移到了外部类的方法中,然后在外部类的方法中再生成一个内部类对象去调用内部类方法。如果此时我们需要往外部类的方法中传入参数,那么外部类的方法形参必须使用 final定义。
换句话说,在方法中定义的内部类只能访问方法中final类型的局部变量,这是因为在方法中定义的局部变量相当于一个常量,它的生命周期超出方法运行的生命周期,由于局部变量被设置为final,所以不能在内部类中改变局部变量的值。
定义在作用域内的内部类:

class Outter {
  private int age = 12;
  public void Print(final boolean x) {    //这里局部变量x必须设置为final类型!
        if(x){
             class Inner {
                 public void inPrint() {
                     System.out.println(age);
                 }
             }
             new Inner().inPrint();
        }       
    }
}
public class test1 {
    public static void main(String[] args) {
        Outter out = new Outter();
        out.Print(true);
    }
}

运行结果: 12

3.匿名内部类

匿名内部类应该是平时我们编写代码时用得最多的,在编写事件监听的代码时使用匿名内部类不但方便,而且使代码更加容易维护。下面这段代码是一段事件监听代码:

scan_bt.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
    // TODO Auto-generated method stub
    }
});
history_bt.setOnClickListener(new OnClickListener() {       
    @Override
    public void onClick(View v) {
    // TODO Auto-generated method stub
    }
});

这段代码为两个按钮设置监听器,这里面就使用了匿名内部类。具体位置是这段:

new OnClickListener() {   
    @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
        }
    }

代码中需要给按钮设置监听器对象,使用匿名内部类能够在实现父类或者接口中的方法情况下同时产生一个相应的对象,但是前提是这个父类或者接口必须先存在才能这样使用。当然像下面这种写法也是可以的,跟上面使用匿名内部类达到效果相同:

private void setListener(){
    scan_bt.setOnClickListener(new Listener1());       
    history_bt.setOnClickListener(new Listener2());
}
class Listener1 implements View.OnClickListener{
    @Override
    public void onClick(View v) {
    // TODO Auto-generated method stub
    }
}
class Listener2 implements View.OnClickListener{
    @Override
    public void onClick(View v) {
    // TODO Auto-generated method stub
    }
}

这种写法虽然能达到一样的效果,但是既冗长又难以维护,所以一般使用匿名内部类的方法来编写事件监听代码。同样的,匿名内部类也是不能有访问修饰符和static修饰符的。
匿名内部类是唯一一种没有构造器的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调。匿名内部类在编译的时候由系统自动起名为Outter$1.class。一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。

4.静态嵌套类

又叫静态局部类、嵌套内部类,就是修饰为static的内部类。声明为static的内部类,不需要内部类对象和外部类对象之间的联系,就是说我们可以直接引用outer.inner,即不需要创建外部类,也不需要创建内部类。

class Outter {
    private static int age = 12;
    static class Inner {
        public void print() {
            System.out.println(age);
        }
    }
}
public class test {
    public static void main(String[] args) {
        Outter.Inner in = new Outter.Inner();
        in.print();
    }
}

运行结果:

12

可以看到,如果用static将内部内静态化,那么内部类就只能访问外部类的静态成员变量,具有局限性。
其次,因为内部类被静态化,因此Outter.Inner可以当做一个整体看,可以直接new 出内部类的对象(通过类名访问static,生不生成外部类对象都没关系)。

以上是对Java内部类的一些学习和总结,纰漏之处希望各位小伙伴友情指点,共同进步。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/66348.html

相关文章

  • (Thinking in Java)第10章 内部

    摘要:内部类中也可以取得这个外部类对象引用。创建成员内部类对象的时候需要外部类对象。另外在方法中的内部类不能加等权限修饰符,只能加和修饰符。可以在接口内部定义内部类,而且他们即使没有修饰,也会自动变成的。 Thinking in Java捞干货,写笔记 一、成员内部类 1.最基本使用 public class Demo { class Contents{ privat...

    Brenner 评论0 收藏0
  • 什么是Java内部

    摘要:内部类一概述把类定义在另一个类的内部,该类就被称为内部类。为什么局部内部类访问局部变量必须加修饰呢因为局部变量是随着方法的调用而调用,使用完毕就消失,而堆内存的数据并不会立即消失。 内部类 (一) 概述 把类定义在另一个类的内部,该类就被称为内部类。 举例:把类Inner定义在类Outer中,类Inner就被称为内部类。 class Outer { class Inner { ...

    Drummor 评论0 收藏0
  • 7. java 内部

    摘要:外部类也可以直接访问内部类的所有属性和方法。匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。创建内部类对象的时刻并不依赖于外围类对象的创建。内部类并没有令人迷惑的关系,他就是一个独立的实体。 基本概念 可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。 广泛意义上的内部类一般来说包括这四种: 成员内部类 局部内部类 静态内部类 匿名内部类 成...

    legendmohe 评论0 收藏0
  • Java编程基础11——面向对象_包&权限修饰符&匿名内部

    摘要:外部类要访问内部类的成员,必须创建对象。前提存在一个类或者接口这里的类可以是具体类也可以是抽象类。 1.package关键字的概述及作用(了解) A:为什么要有包 将字节码(.class)进行分类存放 包其实就是文件夹 B:包的概述 举例: 学生:增加,删除,修改,查询 老师:增加,删除,修改,查询 ... 方案1:按照功能分 com.heima.add ...

    Bryan 评论0 收藏0
  • Java编程思想》笔记10.内部

    摘要:但远不止如此,内部类了解外部类,并能与之通信。内部类还拥有其外围类的所有元素的访问权。普通内部类内不能有域和方法。特点普通内部类对象隐式的保存了外部类对象,但嵌套类并非如此。局部内部类可以访问当前代码块内的常量,以及此外围类的成员。 点击进入我的博客 可以把一个类的定义放在另一个类的定义内部,这就是内部类。Java最晦涩的部分之一。内部类看起来就像是一种代码隐藏机制,将类只与其他类的...

    wslongchen 评论0 收藏0

发表评论

0条评论

jackzou

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<