内部类

内部类:顾名思义,就是在一个类的内部创建一个新类,也就是俗话说的把类的定义置于外围类的里面。

e.g:

public class Test {

class Contents{
private int i = 11;
public int value(){
return i;
}
}
class Destination {
private String label;
Destination(String whereTo){
label = whereTo;
}
String readLabel(){
return label;
}
}
public void ship(String dest){
Contents c = new Contents();
Destination d = new Destination(dest);
System.out.println(d.readLabel());
}
public static void main(String[] args){
Test t = new Test();
t.ship("Tasmania");
}


}

//console

Tasmania

从上看他们的区别也就只是内部类嵌套在Test里面;

2.连接到外部类:

内部类除了只是一种名字隐藏和组织代码的模式,还有其他的用途,当生产一个内部类时,此对象与制造他的外围对象之间天然就有了一种联系,所有她能访问其外围对象的所有成员,且不需要任何特殊条件,也就是内部类还拥有其外围类的所有元素的访问权限。

e.g:

public class Sequence {


private Object[] items;

private int next = 0;

/**

* <b>构造方法</b>
* <br/>
* @param size
*/
public Sequence(int size) {
items = new Object[size];
}

/**

* <b>方法说明:</b>
* <ul>

* </ul>
* @param x
*/
public void add(Object x){
if(next < items.length){
items[next++] = x;
}
}

private class SequenceSelector implements Selector{

private int i = 0;

@Override
public boolean end() {
return i == items.length;
}


@Override
public Object current() {
return items[i];
}


@Override
public void next() {
if(i<items.length){
i++;
}
}

}

public Selector selector(){
return new SequenceSelector();
}

/**
* <b>方法说明:</b>
* <ul>

* </ul>
* @param args 
*/
public static void main(String[] args) {


Sequence sequence = new Sequence(10);

for(int i = 0;i<10;i++)
sequence.add(Integer.toString(i));
Selector selector = sequence.selector();
while(!selector.end()){
System.out.print(selector.current()+",");
selector.next();
}

}

}
interface Selector{

boolean end();

Object current();

void next();

}


3.使用.this与.new


若需要生成对外部类的引用,可以使用外部类的名字后面紧跟圆点和this,这样产生的引用自动地具有正确的类型,这一点在编译器就被知晓并受到检查,因此没有任何运行时开销。

public class DoThis {


void f(){
System.out.println("Dothis.f()");
}
 
void b(){
System.out.println("Dothis.d()");
}
 
public class Inner{
public DoThis outer(){
//
return DoThis.this;
}
}
 
public Inner inner(){
return new Inner();
}

/**
* <b>方法说明:</b>
* <ul>

* </ul>
* @param args 
*/
public static void main(String[] args) {
DoThis dt = new DoThis();

DoThis.Inner dti = dt.inner();
dti.outer().f();
dti.outer().b();
}


}



.new 的作用是在需要让其他某一个对象去创建其某一个内部类的对象,要创建其某个内部类的对象,要实现这个目的,那么则需要在new表达式中提供对其外部类对象的引用


public class DotNew{

public class Inner{}

public static void main(String[] args){

DotNew dn = new DotNew();

//   .new的使用

DotNew.Inner dni = dn.new Inner();

}

}

在拥有外部类对象之前是不可能创建内部类对象的,这是由于内部类对象会暗暗的连接到其创建它的外部类对象上,但若果你创建的是嵌套类(静态内部类),那么则不需要外部类的对象的引用


4.内部类与向上转型:


当将内部类向上转型为其基类,尤其是转型为一个接口的时候,内部类的作用就显现出来了(从实现了某个接口的对象,得到对此接口的引用,与向上转型为这个对象的基类,实质上效果是一样的)。这是因为此内部类是某一个接口的实现,能够完全不可见,且不可用。而所得到的只是指向基类或接口的引用,所以能够很方便的隐藏实现细节。


public class TestParcel {


/**
* <b>方法说明:</b>
* <ul>

* </ul>
* @param args 
*/
public static void main(String[] args) {
Parcel4 p = new Parcel4();
Contents c = p.contents();

Destination d = p.description("Tasmania");

}


}


interface Destination{
// 接口方法默认的都是public
String readLabel();
}
interface Contents{
// 接口方法默认的都是public
int value();
}


class Parcel4{
private class PContents implements Contents{

private int i = 12;


@Override
public int value() {

return i;
}

}

protected class PDestination implements Destination{


private String label;

private PDestination(String whereTo){
label = whereTo;
}

@Override
public String readLabel() {
return label;
}

}

public PDestination description(String s){
return new PDestination(s);
}

public Contents contents(){
return new PContents();
}
}


从这个例子可以看出,内部类PContents 是私有的,private访问权限的,除了Parcel4,其他都不可以访问,内部类PDestination 是包访问权限,也就是只有Parcel4及其子类,还有和Parcel4同一个包中的类能够访问,其他类都不能访问该内部类。甚至可以说是向下转型成private内部类都不可以(或protected内部类,除非是继承自它的子类),因为不能访问其名字,就像在TestParcel类中看到的那样,于是,private内部类给类提供了一种途径,通过这种方式可以完全阻止任何依赖与类型的编码,完全隐藏来实现的细节。


5. 在方法和作用域内的内部类


顾名思义,就是可以在一个方法里面或在任意的作用域定义内部类,这样做的理由如下:

1.实现了某类型的接口,可以创建并返回对其的引用;

2.当解决一些复杂的问题的时候,创建了一个辅助类来完成,但是又不希望这个类时公共可用的


1).展示在方法的作用域内创建一个完整的类-----------------------------------局部内部类

public class Parcel5 {


public Destination destination(String s){

class PDestination implements Destination{

private String label;

private PDestination(String whereTo){
label = whereTo;


@Override
public String readLabel() {
return label;
}

}

return new PDestination(s);
}

/**
* <b>方法说明:</b>
* <ul>

* </ul>
* @param args 
*/
public static void main(String[] args) {
Parcel5 p = new Parcel5();
Destination d = p.destination("Tasmanis");
}


}

PDestinationdestination()方法的一部分,而不是Parcel的一部分,所以在destination()之外不能访问PDestination,在return中返回的其基类的引用,也就是向上转型.


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


一般不需要内部类对象与其外围类对象之间有联系,那么可以将内部类申明为static。

嵌套类意味着:

1)要创建嵌套类的对象,并不需要其外围类的对象;

2)不能从嵌套类的对象中访问非静态的外围类对象。

普通内部类和嵌套类的区别:普通内部类的字段和方法,只能放在类的外部层次上,所以普通内部类不能有static数据和static字段,也不能包含嵌套类。但反之嵌套类则可以包含这些所有的东西


7.接口内部的类


一般情况下,不能再接口内部放置任何代码,但嵌套类却可以作为接口的一部分。放到接口中的任何类都会自动变成public和static,由于类时static的,只是将嵌套类置于接口的命名空间内,并不违反接口的规则,甚至可以在内部类中实现其外围接口,如下、:

public interface ClassInInterface{

void howdy();

class Test implements ClassInInterface{

public void howdy(){

System.out.println("Howdy!");

}

public static void main(String[] args){

new Test().howdy();

}

}

}


内部类的作用 : 每个内部类都能独立的继承自一个接口的实现,无论外围类是否已经继承了某个接口的实现,对于内部类都没有影响,甚至可以说这是一种多继承的解决办法


内部类的其他特性:1).内部类可以有多个实例,每个实例都有自己的状态信息,且和外围类的实例互相独立;

     2).在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或继承同一个类;

      3).创建内部类对象的时刻并不依赖与外围类对象的创建;

      4).内部类并没有令人迷惑的"is - a" 关系,就是一个独立的实体。


8.闭包和回调:

闭包:一个可调用的对象,记录了一些信息,这些信息来自语创建它的作用域,从定义可以看出内部类时面向对象的闭包,因为它不仅包含外围类对象(创建内部类的作用域)的信息,还自动拥有了指向此外围类对象的引用。在这个作用域中,内部类有权操作所有的成员,包括private成员。

有些人认为java应该包含某种类似指针的机制,以此来允许回调(callback),通过回调,对象能够携带一些信息,在这些信息允许它在稍后的某个时刻调用初始的对象,通过内部类提供闭包的功能时解决这个问题的好方案,比指针更安全。

e.g:

public class CallBack {


/**
* <b>方法说明:</b>
* <ul>

* </ul>
* @param args 
*/
public static void main(String[] args) {
Callee1 c1 = new Callee1();
Callee2 c2 = new Callee2();
MyIncrement.f(c2);
Caller caller1 = new Caller(c1);
Caller caller2 = new Caller(c2.getCallBackReference());
caller1.go();
caller1.go();
caller2.go();
caller2.go();
}


}


// create a interface
interface Incrementable{

void increment();

}


// a simple class to implement the interface
class Callee1 implements Incrementable{


private int i = 0 ;


@Override
public void increment() {


i++;
System.out.println(i);
}

}


class MyIncrement{
public void increment(){
System.out.println("other operation");
}

static void f(MyIncrement mi){
mi.increment();
}
}


// 由于这个类有一个increment(),想要在其他方法里面实现,那么只有使用内部类
class Callee2 extends MyIncrement{
private int i = 0;
public void increment(){
super.increment();
i++;
System.out.println(i);
}

private class Closure implements Incrementable{


@Override
public void increment() {
// 指定调用外部方法,防止死循环
Callee2.this.increment();
}

}
Incrementable getCallBackReference(){
return new Closure();
}
}


class Caller{

private Incrementable callbackReference;

Caller(Incrementable cbh){
callbackReference = cbh;
}

void go(){
callbackReference.increment();
}

}

9.内部类的继承:由于内部类构造器必须连接指向其外围类的引用。所以在继承内部类的时候,指向外围类对象的引用必须初始化,在派生类中不在存在可连接的默认对象;

public class InnerClassExtends extends WithInner.Inners{


InnerClassExtends(WithInner w){
w.super();
}

/**
* <b>方法说明:</b>
* <ul>

* </ul>
* @param args 
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
InnerClassExtends m = new InnerClassExtends(new WithInner());
m.test();
m.test();
}
}


class WithInner{
public void tt(){

}
class Inners{

public void test(){}
}
}


















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值