java中的内部类
来源:互联网 发布:数据库订单管理模板 编辑:程序博客网 时间:2024/06/15 03:31
可将一个类定义置入另一个类定义中。这就叫作“内部类”。内部类对我们非常有用,因为利用它可对那些逻辑上相互联系的类进行分组,并可控制一个类在另一个类里的“可见性”。
为何要使用内部类,有以下比较基本的原因:
(1) 我们准备实现某种形式的接口,使自己能创建和返回一个句柄。
(2) 要解决一个复杂的问题,并希望创建一个类,用来辅助自己的程序方案。同时不愿意把它公开。(通过内部类隐藏实施细节)
基本注意点
1.普通类(指的是非内部类)不可设为private或 protected——只允许 public或者“友好的”,而内部类可以,这么做可将具体的实施细节完全隐藏起来。
2.对于局部内部类和匿名类(尤其是if语句内的局部内部类),并不意味着内部类是有条件创建的——它会随同其他所有东西得到编译。然而,在定义它的那个作用域之外,它是不可使用的。
3.对于局部内部类和匿名类,和局部变量一样,不能被public,protected,private和static修饰。局部内部类(含匿名类)只能访问局部方法中定义的final类型的局部变量。(注意:这里说的是所处方法作用域内的局部变量,如果是外部类中的局部变量,可直接使用)
4.非static内部类不能定义static变量,除非是final类型。
5.内部类拥有对封装类所有元素的访问权限。(当然,如果内部类是static的,必须变量也是static的。究其原因,静态内部类没有指向外部的引用)
6.一般来说,接口中不能有具体实现。但内部类可以作为接口的一部分。(通常是static内部类,否则可能没有实际意义。)
Java中的内部类共分为四种:
成员内部类member inner class
局部内部类local inner class
匿名内部类anonymous inner class
静态内部类static inner class (also called nested class)
成员内部类
成员内部类基本用法
abstract class Contents {abstract public int value();}interface Destination {String readLabel();}class Parcel3 {private class PContents extends Contents {private int i = 11;public int value() {return i; } }protected class PDestination implements Destination {private String label;private PDestination(String whereTo) {label = whereTo;}public String readLabel() {return label; }} public Destination dest(String s) { return new PDestination(s);}public Contents cont() {return new PContents();}} public static void Test2(){ Parcel3 p = new Parcel3(); Contents c = p.cont(); Destination d = p.dest("Tanzania"); // Illegal -- can't access private class: //! Parcel3.PContents c = p.new PContents(); }
局部内部类
在一个方法内定义内部类
class Parcel4 {public Destination dest(String s) {class PDestination implements Destination {private String label;private PDestination(String whereTo) {label = whereTo;}public String readLabel() { return label; }}return new PDestination(s);}public static void main(String[] args) {Parcel4 p = new Parcel4();Destination d = p.dest("Tanzania");}}
在任意作用域内定义内部类
class Parcel5 {private void internalTracking(boolean b) {if(b) {class TrackingSlip {private String id;TrackingSlip(String s) {id = s;}String getSlip() { return id;}}TrackingSlip ts = new TrackingSlip("slip");String s = ts.getSlip();}// TrackingSlip ts = new TrackingSlip("x");//不可访问,超出作用域}public void track() { internalTracking(true);}public static void main(String[] args) {Parcel5 p = new Parcel5();p.track();}}
匿名内部类
匿名内部类就是没有名字的局部内部类,不使用关键字class, extends, implements, 没有构造方法。匿名内部类隐式地继承了一个父类或者实现了一个接口。也就是说,匿名类可以继承一个基础类,也可以实现一个接口,但不需要使用关键字,而是直接覆盖父类。但匿名内部类不能同时实现一个接口和继承一个类,也不能实现多个接口。如果匿名类实现了一个接口,该类是Object类的直接子类。
匿名内部类基本用法
class Wrapping {private int i;public Wrapping(int x) { i = x; }public int value() { return i;}} interface Wrapping2 {public int value();}//匿名类class Parcel7 {public Wrapping wrap(int x) {// Base constructor call:return new Wrapping(x){public int value() {return super.value() * 47;}}; // Semicolon required}public Wrapping2 wrap2() {//既可以是一个基础类,也可以是一个接口return new Wrapping2(){public int value() {return 0;}};}public static void main(String[] args) {Parcel7 p = new Parcel7();Wrapping w = p.wrap(10);Wrapping2 w2=p.wrap2();}}
匿名内部类不可以有构造方法,但还是可以对变量进行初始化的。
匿名类变量初始化
class Parcel8 {// Argument must be final to use inside// anonymous inner class:public Destination dest(final String dest) {return new Destination() {private String label = dest;public String readLabel() {return label;}};}public static void main(String[] args) {Parcel8 p = new Parcel8();Destination d = p.dest("Tanzania");System.out.println(d.readLabel());}}利用构造代码块初始化
class Parcel9 {public Destination dest(final String dest) {return new Destination() {{ System.out.println("代码块初始化!");}private String label = dest;public String readLabel() { return label;}};}public static void main(String[] args) {Parcel9 p = new Parcel9();Destination d = p.dest("Tanzania");}}但构造代码块毕竟不是构造器,不能进行过载。
静态内部类
static内部类并不是说一个内部类是static 的。static内部类意味着:
(1) 创建一个 static内部类的对象,我们不需要一个外部类对象。
(2) 不能从 static内部类的一个对象中访问一个外部类对象。(除非该对象是static的)
静态内部类基本用法
class Parcel10 {//public int a=0;public static int a=0;private static class PContents extends Contents {private int i = 11;public int value() { return i; }}protected static class PDestination implements Destination {private String label;private PDestination(String whereTo) {label = whereTo;}public String readLabel() { return label; }}public static Destination dest(String s) {return new PDestination(s);}public static Contents cont() {return new PContents();}public static Parcel101 getP(){return new Parcel101();}public static int getA(){return a; //a也必须是static}public static void main(String[] args) {Contents c = cont();Destination d = dest("Tanzania");//这里没有显示调用static内部类,但方法是static,所以内部类必须是static的Parcel101 p= getP();//外部类没有static一说,可直接使用int b=getA();//变量同理,由于方法是static,因此变量必须是static}}
接口中的静态内部类
以下为接口中内部类的一种用法,利用内部类编写公用测试方法。
class QuestionMain implements ITest{ public static void main(String[] args) { ITest.TestInternal.test(new QuestionMain()); } public void print() { System.out.println("QuestionMain.print"); }}//接口中的内部类interface ITest { void print(); public static class TestInternal { public static void test(ITest test) { test.print(); } }}
除此之外,内部类还有一些其它特性:
链接到外部类
interface Selector {boolean end();Object current();void next();}class Sequence {private Object[] o;private int next = 0;public Sequence(int size) {o = new Object[size];}public void add(Object x) {if(next < o.length) {o[next] = x;next++;}}private class SSelector implements Selector {int i = 0;public boolean end() {return i == o.length;}public Object current() {return o[i];}public void next() {if(i < o.length) i++;}}public Selector getSelector() {return new SSelector();}public static void main(String[] args) {Sequence s = new Sequence(10);for(int i = 0; i < 10; i++)s.add(Integer.toString(i));Selector sl = s.getSelector();while(!sl.end()) {System.out.println((String)sl.current());sl.next();}}}
引用外部类对象
class Parcel11 {int a=1;int b=1;class Contents {private int i = 11;public int value() {return i; }}class Destination {int a=2;private String label;Destination(String whereTo) {label = whereTo;} String readLabel() {return label; }void getValue(){System.out.println(this.a);//this指向的是内部类//System.out.println(this.b); //内部类中无此值}}public static void main(String[] args) {Parcel11 p = new Parcel11();Parcel11.Contents c = p.new Contents();//非static的内部类必须通过外部类引用Parcel11.Destination d =p.new Destination("Tanzania");//不能绕过外部类直接为非static的开辟空间,所以采用这种写法d.getValue();//Parcel11.Contents c2 = new Parcel11.Contents(); //报错}}
内部类继承
内部类继承比较特殊,子类必须有一个构造方法,且把外部类的一个对象作为参数。只有这样,才能保证内部类正常创建。
class WithInner {class Inner {}}class InheritInner extends WithInner.Inner {//! InheritInner() {} // Won't compileInheritInner(WithInner wi) {wi.super(); }public static void main(String[] args) {WithInner wi = new WithInner();InheritInner ii = new InheritInner(wi);}<strong>}</strong>
外部类被继承,内部类是否被覆盖
例子如下,被继承的只是外部类,子类中有一个和内部类同名的内部类,但这两个内部类并不存在继承关系
class Egg {protected class Yolk {public Yolk() {System.out.println("Egg.Yolk()");}}private Yolk y;public Egg() {System.out.println("New Egg()");y = new Yolk();}}class BigEgg extends Egg {public class Yolk {public Yolk() {System.out.println("BigEgg.Yolk()");}}public static void main(String[] args) {new BigEgg();}}
输出如下,Yolk并没有被继承
New Egg()Egg.Yolk()
如果希望内部类也被继承,需要改动程序(这里是内部类继承内部类,同时外部类继承外部类,注意与上文的外部类继承内部类区分开来。)
class Egg2 {protected class Yolk {public Yolk() {System.out.println("Egg2.Yolk()");}public void f() {System.out.println("Egg2.Yolk.f()");}}private Yolk y = new Yolk();public Egg2() {System.out.println("New Egg2()");}public void insertYolk(Yolk yy) { y = yy; }public void g() { y.f();}}class BigEgg2 extends Egg2 {public class Yolk extends Egg2.Yolk {public Yolk() {System.out.println("BigEgg2.Yolk()");}public void f() {System.out.println("BigEgg2.Yolk.f()");}}public BigEgg2() { insertYolk(new Yolk());}public static void main(String[] args) {Egg2 e2 = new BigEgg2();e2.g();}}
输出如下,Yolk方法被覆盖
Egg2.Yolk()New Egg2()Egg2.Yolk()BigEgg2.Yolk()BigEgg2.Yolk.f()
利用内部类控制框架:
内部类可以做这些事情:
(1) 在单独一个类里表达一个控制框架应用的全部实施细节,从而完整地封装与那个实施有关的所有东西。内部类用于表达多种不同类型的action(),它们用于解决实际的问题。除此以外,后续的例子使用了private内部类,所以实施细节会完全隐藏起来,可以安全地修改。
(2) 内部类使我们具体的实施变得更加巧妙,因为能方便地访问外部类的任何成员。若不具备这种能力,代码看起来就可能没那么使人舒服,最后不得不寻找其他方法解决。
例子:
abstract class Event {private long evtTime;public Event(long eventTime) {evtTime = eventTime;}public boolean ready() {return System.currentTimeMillis() >= evtTime;}abstract public void action();abstract public String description();}class EventSet {private Event[] events = new Event[100];private int index = 0;private int next = 0;public void add(Event e) {if(index >= events.length)return; // (In real life, throw exception)events[index++] = e;}public Event getNext() {boolean looped = false;int start = next;do {next = (next + 1) % events.length;// See if it has looped to the beginning:if(start == next) looped = true;// If it loops past start, the list// is empty:if((next == (start + 1) % events.length)&& looped)return null;} while(events[next] == null);return events[next];}public void removeCurrent() {events[next] = null;}}class Controller {private EventSet es = new EventSet();public void addEvent(Event c) { es.add(c);}public void run() {Event e;while((e = es.getNext()) != null) {if(e.ready()) {e.action();System.out.println(e.description());es.removeCurrent();}}}} class GreenhouseControls extends Controller {private boolean light = false;private boolean water = false;private String thermostat = "Day";private class LightOn extends Event {LightOn(long eventTime) {super(eventTime);}public void action() {// Put hardware control code here to// physically turn on the light.light = true;}public String description() {return "Light is on";}}private class LightOff extends Event {public LightOff(long eventTime) {super(eventTime);}public void action() {// Put hardware control code here to// physically turn off the light.light = false;}public String description() {return "Light is off";}}private class WaterOn extends Event {public WaterOn(long eventTime) {super(eventTime);}public void action() {// Put hardware control code herewater = true;}public String description() {return "Greenhouse water is on";}}private class WaterOff extends Event {public WaterOff(long eventTime) {super(eventTime);}public void action() {// Put hardware control code herewater = false;}public String description() {return "Greenhouse water is off";}}private class ThermostatNight extends Event {public ThermostatNight(long eventTime) {super(eventTime);}public void action() {// Put hardware control code herethermostat = "Night";}public String description() {return "Thermostat on night setting";}}private class ThermostatDay extends Event {public ThermostatDay(long eventTime) {super(eventTime);}public void action() {// Put hardware control code herethermostat = "Day";}public String description() {return "Thermostat on day setting";}}// An example of an action() that inserts a// new one of itself into the event list:private int rings;private class Bell extends Event {public Bell(long eventTime) {super(eventTime);}public void action() {// Ring bell every 2 seconds, rings times:System.out.println("Bing!");if(--rings > 0)addEvent(new Bell(System.currentTimeMillis() + 2000));}public String description() {return "Ring bell";}}private class Restart extends Event {public Restart(long eventTime) {super(eventTime);}public void action() {long tm = System.currentTimeMillis();// Instead of hard-wiring, you could parse// configuration information from a text// file here:rings = 5;addEvent(new ThermostatNight(tm));addEvent(new LightOn(tm + 1000));addEvent(new LightOff(tm + 2000));addEvent(new WaterOn(tm + 3000));addEvent(new WaterOff(tm + 8000));addEvent(new Bell(tm + 9000));addEvent(new ThermostatDay(tm + 10000));// Can even add a Restart object!addEvent(new Restart(tm + 20000));}public String description() {return "Restarting system";}}public static void main(String[] args) {GreenhouseControls gc =new GreenhouseControls();long tm = System.currentTimeMillis();gc.addEvent(gc.new Restart(tm));gc.run();}}
- java中的内部类
- JAVA中的内部类
- java 中的内部类
- java中的内部类
- Java中的内部类
- JAVA 中的内部类
- java中的内部类
- java 中的内部类
- java中的内部类
- Java中的内部类
- java中的内部类
- Java 中的内部类
- java 中的内部类
- java中的内部类
- Java中的内部类
- java中的内部类
- Java中的内部类
- java中的内部类
- 关于platform_led驱动的问题
- Identity Mappings in Deep Residual Networks
- How to enter an End-Of-File from the keyboard
- pinyin4j
- Codeforces 691A. Fashion in Berland (模拟)
- java中的内部类
- 树(1)把二叉查找树转换成有序的双向链表
- hdu 5154 Harry and Magical Computer(拓扑排序)
- Java_JVM_逃逸分析技术_栈上分配_标量替换
- 相对布局属性讲解
- 高可用集群的概念理解
- 构造数组的MaxTree
- php set get asset unset
- POJ 1200