Java 内部类(1): 基本语法

来源:互联网 发布:北京少儿编程培训班 编辑:程序博客网 时间:2024/06/12 22:15

可以将一个类的定义放在另一个类的内部,这就是内部类。内部类的表面意义一目了然,不过内部类的实现语法还是稍显繁琐。

内部类的分类

:内部类主要分为:普通内部类,匿名内部类,局部内部类,嵌套内部类(静态内部类)。

普通内部类

普通内部类内不能有静态成员变量和静态方法

    public class Outer{        class Inner{            private String name;            public Inner(String name){                this.name = name;            }            public void setName(String name){                this.name = name;            }            public String getName(){                return name;            }        }        public Inner getInner(String name){            return new Inner(name);        }        public static void main(String[] args){            Outer out = new Outer();            Inner inner = out.getInner("inner");            System.out.println(inner.getName());        }    }

普通内部类拥有对外部类的全部访问权,它能够与外部类进行通信并且可以操作外部类。当某个外部类对象创建了一个内部类对象,该内部类对象会秘密的保留一个指向创建它的外部类对象的引用。当内部类中访问外部类成员时,就是通过这个隐藏引用来拥有外部类的访问权。换句话说,内部类对象只能在与其外围类的对象关联的情况下才能创建(不包括静态内部类),构建内部类对象时,需要一个指向其外部类的引用,如果找不到这个引用,则编译器报错。
普通内部类不能含有静态成员变量和静态方法。

最典型的应用就是外部类有一个公共方法a,该方法返回一个内部类(该内部类是private的并且实现了某个公共接口,外部无法直接访问类,只能通过接口)对象的引用,也就是返回类型为公共接口类型
这样既可以得到一个公共接口的实现类,又完美隐藏了其实现细节,客户端不知道实现类的名字(因为该类是私有的,客户端无法访问),只能通过公共方法a得到它。java集合中的迭代器Iterator()就是其一。
例如:

//接口类public interface Selector {    boolean end();    void next();    Object curr();}//主类public class Outer_3 {    class SelectorImpl implements Selector {        @Override            public boolean end() {                return false;            }            @Override            public void next() {            }            @Override            public Object curr() {                return null;            }    }    public Selector selector() {        return new SelectorImpl();    }    public static void main(String[] args) {        Outer_3 outer3 = new Outer_3();        Selector selector = outer3.selector();        System.out.println(selector.end());    }}

匿名内部类

   匿名内部类的使用基本上需要符合一下几点:
        
- 匿名内部类只能使用一次,创建匿名内部类的同时也会创建该类的一个对象,之后该类的定义消失。通常用来简化代码编写。
- 匿名内部类内部无法定义构造函数
- 匿名内部类不能有静态成员变量或静态方法
- 匿名内部类是局部内部类,所以局部内部类的限制匿名内部类也有
- 匿名内部类必须继承某个类或者实现某个接口(因为匿名,所以无法访问,要想使用只能通过向上转型为父类或者接口)
匿名内部类的典型应用是用来开启一个线程:

public class Main{    public static void main(String[] args){        Runnable r = new Runnable(){                public void run(){                      System.out.println("new Tread is running");                }            };        Thread thread = new Thread(r);        thread.start();    }}

局部内部类:

//局部内部类public class Out_4 {    public void inner(final String name) { //jdk8以下必须用final修饰,jdk8虽然不是必须,但是在类内部也是无法改变该变量的。        class Inner {            private String sname;            Inner(){                //name = name = "";  编译错误,局部内类部无法改变方法参数                this.sname = name;            }            Out_4 getOut() {                return Out_4.this;            }        }        System.out.println(new Inner().sname);        System.out.println(new Inner().getOut());    }    public static void main(String[] args) {        Out_4 out_4 = new Out_4();        out_4.inner("out_4");        //out_4.new Inner(); 在局部外部类所在的方法外部无法访问局部内部类    }}

嵌套内部类(静态内部类)

public class Out_5 {    private int i;    static private String j;    public Out_5(int i,String jj){        this.i = i;        j = jj;    }    public static void staticMethod(){    }    static public class Inner {        public  int x;        private int y;        public Inner(int x,int y){            this.x = x;            this.y = y;        }        public int getX(){            return x;        }        public int getY(){            return y;        }        public void print(){            System.out.println(j+":"+x+":"+y);;            staticMethod();;            //System.out.println(i);  //静态内部类不能访问外部类的非静态成员        }    }    public static void main(String[] args) {        Out_5.Inner inner = new Inner(1,2);        Out_5.Inner inner1 = new Inner(3,4);        inner.print();   //null:1:2        inner1.print();  //null:3:4        Out_5 out_5 = new Out_5(5,"10");        System.out.println(out_5.i+":"+out_5.j);  //5:10        Out_5 out_ = new Out_5(5,"15");        System.out.println(out_.i+":"+out_.j);  //5:15        inner.print();   15:1:2    }}

静态内部类能够访问外部类的静态成员,除了创建时要在前面加上外部类名称.之外,跟普通静态类没什么区别。

静态内部类的特殊用途:接口内部的嵌套类。你放到接口中的类自动是public和static的,并不违反接口的语法。
通常情况下,接口内部不能放置任何代码,但如果你想要实现该接口的所有实现类共享一段公共代码,可以考虑在接口内定义静态类。
这有点类似于抽象类的非抽象方法。

//接口类ClassInInterfacepublic interface ClassInInterface {    void f();    class Test{ //接口中的类自动是static,所以不需要额外加static        private String name;        public String getName() {            return name;        }        public void setName(String name) {            this.name = name;        }    }}//接口实现类public class ClassInInterfaceImpl implements ClassInInterface {    @Override    public void f() {        System.out.println("method f()");    }    public static void main(String[] args) {          ClassInInterfaceImpl instance = new         ClassInInterfaceImpl();        Test test = new Test();        test.setName("name");        System.out.println(test.getName());    }}

new 和 this

非嵌套类情况下,内部类拥有对外部类的全部访问权,内部类内部拥有一条外部类的引用,那么如何在内部类中得到外部类的引用呢,这就是this的作用了。另外内部类的创建依赖于外部类的某个实例对象,如何由外部类对象创建一个内部类对象,这就需要用到new的新用法。示例如下

public Outer{    class Inner{        private String name;        Inner(String name){            this.name = name;        }        public String getName(){            return this.name;        }        public Outer getOuter(){        //外部类名字.this            return Outer.this;        }    }    public static void main(String[] args){        Outer out = new Outer();        //外部对象.new 内部类构造器(匿名内部类无法用这种方式,但匿名内部类通用可以访问到外部类)        Inner inner = out.new Inner("inner");        System.out.println(inner.getName());        Outer out2 = inner.getOuter();        System.out.println(out==out2); // true    }}
原创粉丝点击