博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(转)java内部类总结
阅读量:4151 次
发布时间:2019-05-25

本文共 4860 字,大约阅读时间需要 16 分钟。

 

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

内部类作为外部类的一个成员,并且依附于外部类而存在的。
内部类可为静态,可用protected和private修饰。(而外部类不可以:外部类只能使用public和默认的)。

内部类分为:成员内部类、局部内部类、静态内部类、匿名内部类

 

几种内部类的共性:

A、内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类命和$符号,比如Outer.class和Outer$Inner.class。
B、内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的。

成员内部类:

成员内部类:形式如下:

 

class Outer {    class Inner{}}

 

 

编译上述代码会产生两个文件:Outer.class和Outer$Inner.class。

成员内部类内不允许有任何静态声明!下面代码不能通过编译。

 

 

class Inner{      static int a = 10;}

 

 

能够访问成员内部类的唯一途径就是通过外部类的对象!

下面看一个成员内部类的例子:

 

public interface Contents {    int value();}public interface Destination {    String readLabel();}public class Goods {    private class Content implements Contents {        private int i = 11;        public int value() {            return i;        }    }    protected class GDestination implements Destination {        private String label;        private GDestination(String whereTo) {            label = whereTo;        }        public String readLabel() {            return label;        }    }    public Destination dest(String s) {        return new GDestination(s);    }    public Contents cont() {        return new Content();    }}class TestGoods {    public static void main(String[] args) {        Goods p = new Goods();        Contents c = p.cont();        Destination d = p.dest("Beijing");    }}

 内部类的第一个好处就体现出来了 隐藏你不想让别人知道的操作,也即封装性。

同时,我们也发现了在外部类作用范围之外得到内部类对象的第一个方法,那就是利用其外部类的方法创建并返回。上例中的cont()和dest()方法就是这么做的。那么还有没有别的方法呢?当然有,其语法格式如下:

 

 

outerObject=new outerClass(Constructor Parameters);outerClass.innerClass innerObject=outerObject.new InnerClass(Constructor Parameters);

 

 

注意在创建非静态内部类对象时,一定要先创建起相应的外部类对象。至于原因: 非静态内部类对象有着指向其外部类对象的引用。

内部类的this引用:普通的类可以用this引用当前的对象,内部类也是如此。但是假若内部类想引用外部类当前的对象呢?用“外部类名”.this;的形式,如下例的Outer.this:

 

class Outer {    class Inner{        public void seeOuter(){            System.out.println(this);            System.out.println(Outer.this);        }    }}

 对于普通的类,可用的修饰符有final、abstract、strictfp、public和默认的包访问。

但是成员内部类更像一个成员变量和方法,他可用的修饰符有:final、abstract、public、private、protected、strictfp和static。
不过一旦用static修饰内部类,它就变成静态内部类了。

 

 

静态内部类:

 

和非静态内部类相比,区别就在于静态内部类没有了指向外部的引用。除此之外,在任何非静态内部类中,都不能有静态数据,静态方法或者又一个静态内部类(内部类的嵌套可以不止一层)。不过静态内部类中却可以拥有这一切。这也算是两者的第二个区别吧。

 

public class StaticInnerClassDemo {    protected int protected_k = 2;    public int public_n = 3;    public static int public_static_j;         static class InnerClass{        void innerDisplay(){            //只能访问外部类的静态变量和静态方法            System.out.println(public_static_j);        }    }    public static void main(String[] args) {        new StaticInnerClassDemo();        InnerClass inner=new InnerClass();        inner.innerDisplay();    }}

 

 

局部内部类

 

Java内部类也可以是局部的,它可以定义在一个方法甚至一个代码块之内。

 

public class PartInnerClassDemo {    private int private_m = 1;    protected int protected_k = 2;    public int public_n = 3;     public void function() {        final int num = 0;        class InnerClass {            public void innerDisplay() {                System.out.println(private_m);                System.out.println(protected_k);                System.out.println(public_n);                // 此处的num必须是final                System.out.println(num);            }        }        new InnerClass().innerDisplay();    }     public static void main(String[] args) {        PartInnerClassDemo outer = new PartInnerClassDemo();        outer.function();    }}

 

 

A、局部内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。

B、局部内部类对象不能使用该内部类所在方法的非final局部变量。
因 为方法的局部变量位于栈上,只存在于该方法的生命期内。当一个方法结束,其栈结构被删除,局部变量成为历史。但是该方法结束之后,在方法内创建的内部类对 象可能仍然存在于堆中!例如,如果对它的引用被传递到其他某些代码,并存储在一个成员变量内。正因为不能保证局部变量的存活期和方法内部类对象的一样长, 所以内部类对象不能使用它们。

局部内部类的修饰符:与成员内部类不同,局部内部类更像一个局部变量。可以用于修饰局部内部类的只有final和abstract。

静态方法内的局部内部类:

静态方法是没有this引用的,因此在静态方法内的内部类遭受同样的待遇,即:只能访问外部类的静态成员。

 

类匿名内部

顾名思义,没有名字的内部类。表面上看起来它们似乎有名字,实际那不是它们的名字。

 

继承式的匿名内部类

 

class Car {    public void drive(){        System.out.println("Driving a car!");    }} class Test{    public static void main(String[] args) {        Car car = new Car(){            public void drive(){                System.out.println("Driving another car!");            }        };        car.drive();    }}

 

 

结果输出了:Driving another car! Car引用变量不是引用Car对象,而是Car匿名子类的对象。

建立匿名内部类的关键点是重写父类的一个或多个方法。再强调一下,是重写父类的方法,而不是创建新的方法。因为用父类的引用不可能调用父类本身没有的方法!创建新的方法是多余的。简言之,参考多态。

 

接口式的匿名内部类

interface  Vehicle {      public void drive();  }     class Test{      public static void main(String[] args) {          Vehicle v = new Vehicle(){              public void drive(){                  System.out.println("Driving a car!");              }          };          v.drive();      }  }

 上面的代码很怪,好像是在实例化一个接口。事实并非如此,接口式的匿名内部类是实现了一个接口的匿名类。而且只能实现一个接口

 

参数式的匿名内部类

class Bar{    void doStuff(Foo f){}} interface Foo{    void foo();} class Test{    static void go(){        Bar b = new Bar();        b.doStuff(new Foo(){            public void foo(){                System.out.println("foofy");            }        });    }}

 

转载地址:http://nvlti.baihongyu.com/

你可能感兴趣的文章
oracle函数trunc的使用
查看>>
MySQL 存储过程或者函数中传参数实现where id in(1,2,3,...)IN条件拼接
查看>>
java反编译
查看>>
Class.forName( )你搞懂了吗?——转
查看>>
jarFile
查看>>
EJB3.0定时发送jms(发布/定阅)方式
查看>>
EJB与JAVA BEAN_J2EE的异步消息机制
查看>>
数学等于号是=那三个横杠是什么符
查看>>
HTTP协议详解
查看>>
java多线程中的join方法详解
查看>>
ECLIPSE远程调试出现如下问题 ECLIPSE中调试代码提示找不到源
查看>>
java abstract修饰符
查看>>
数组分为两部分,使得其和相差最小
查看>>
java抽象类和接口
查看>>
有趣的排序——百度2017春招
查看>>
二叉树的最近公共祖先LCA
查看>>
数组中累加和为定值K的最长子数组长度
查看>>
素数对--腾讯2017校招编程
查看>>
JAVA集合--ArrayList实现原理
查看>>
synchronized与Lock
查看>>