Java编程思想第四版第十章学习——内部类(1)

原创 2016年05月30日 23:45:45

内部类是指在一个外部类的内部再定义一个类。类名不需要和文件名相同。

1、成员内部类

成员内部类,就是作为外部类的成员,可以直接使用外部类的所有成员和方法,即使是private的。同时外部类要访问内部类的所有成员变量/方法,则需要通过内部类的对象来获取。
注意:成员内部类不能含有static的变量和方法。因为成员内部类需要先创建了外部类,才能创建它自己的。

2、成员内部类的引用和创建

在内部类要生成对外部类对象的引用,可以使用外部类的名字后紧跟”.this”。而想直接创建内部类的对象,必须使用外部类的对象来创建该内部类对象,可以使用外部类的变量名后紧跟“.new”。注意,在外部类对象之前不能创建内部类对象,除非创建的是嵌套类(静态内部类)。

3、局部内部类——在方法和作用域中定义内部类

可以在一个方法里面或者在任意的作用域内定义内部类。这么做有两个好处:
(1)可以实现某个接口,从而可以创建并返回对其的引用
(2)创建一个类来辅助解决复杂问题,并且这个类是不可用的。

//定义在方法之内的内部类——Java编程思想例子
public class Parcel4 { 
    public Destination destination(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.destination("Tasmania"); 
    } 
} 
//定义在if作用域的内部类——Java编程思想例子
public 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(); 
        } 
    } 

    public void track() { 
        internalTracking(true); 
    } 

    public static void main(String[] args) { 
        Parcel5 p = new Parcel5(); 
        p.track(); 
    } 
} 

局部内部类也像别的类一样进行编译,但只是作用域不同而已,只在该方法或条件的作用域内才能使用,退出这些作用域后无法引用的。

4、匿名内部类

匿名内部类创建格式如下:

new 父类构造器(参数列表)|实现接口()    
    {    
     //匿名内部类的类体部分    
    } 

从格式上可以发现,使用匿名构造类必须要继承一个父类或者实现一个接口,且不能同时发生。匿名构造类没有class关键字,直接使用new来生成一个对象的引用(隐式)。例子如下:

interface Hello{
     void say();
}

public class Dada{
    public static void main(String[] args){
        Hello h = new Hello(){
            public void say(){
             System.out.println("C++");
            }
        };
        h.say();
    }
}/*Output
C++
*///
abstract class Hello{
    public abstract void say();
}

public class Dada{
    public static void main(String[] args){
        Hello h = new Hello(){
            public void say(){
             System.out.println("C++");
            }
        };
        h.say();
    }
}/*Output
C++
*///

注意
在使用匿名内部类的过程中,我们需要注意如下几点:
1、使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。
2、匿名内部类中是不能定义构造函数的。
3、匿名内部类中不能存在任何的静态成员变量和静态方法。
4、匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。
5、匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
6、匿名内部类仅能使用一次,创建匿名内部类时它会立即创建一个该类的实例,该类的定义会立即消失,所以匿名内部类是不能够被重复使用。

方法的形参需要设置为final
给匿名内部类传递参数的时候,若该形参在内部类中需要被使用,那么该形参必须要为final。也就是说:当所在的方法的形参需要被内部类里面使用时,该形参必须为final。例如

public class OuterClass {  
    public void display(final String name,String age){  
        class InnerClass{  
            void display(){  
                System.out.println(name);  
            }  
        }  
    }  
}  

内部类并不是直接调用方法传递的参数,而是利用自身的构造器对传入的参数进行备份,自己内部方法调用的实际上是自己的属性而不是外部方法传递进来的参数。
但是为什么要加final呢?因为为了保持内部类和外部类的形参的一致性。通过拷贝引用,内部类为了避免引用值发生改变,如外部类的方法修改而导致内部类得到的值不一致。于是就用final让引用不可改变。

匿名内部类的初始化
匿名内部类中没有构造器,一般通过代码块来完成初始化工作。

public class Parcel10{
    public Destination
    destination (final String dest,final float price){
        return new Destination(){
            private int cost;
            {
                cost = Math.round(price);
                if(cost>100)
                  System.out.println("Over budget!");
            }
            private String label = dest;
            public String readLabel() {return label;}
        };
    }
    public static void main(String[] args){
        Parcel10 p = new Parcel10();
        Destination d = p.destination("Tasmania",101.395F);
    }
}/*Output
Over budget!
*///

5、嵌套类

如果不需要内部类与其外围类对象之间的联系,可以将内部类声明为static,通常称为嵌套类。
嵌套类与普通内部类的区别:
普通内部类对象隐式地保存了一个引用,指向创建它的外围类对象,而要创建嵌套类对象,不需要其外围类的对象,也不能从嵌套类的对象中访问非静态的外围类对象。

接口内部的类
正常情况下,不能在接口内部放置任何代码。但嵌套类可以作为接口的一部分,放到接口中的任何类都自动地是public和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();
    }
  }
}/*Output:
Howdy!
*///

测试小技巧:
如果在每个类中都编写一个main()方法来测试这个类,那就必须带着那些已经编译过的额外代码,这带来额外的开销。此时可以用嵌套类来放置测试代码。

public class TestBed{
 public void f() {System.out.println("f()");}
 public static class Tester {
    public static void main(String[] args){
    TestBed t = new TestBed();
    t.f();
    }
  }
}/*Output:
f()
*///

在编译后,上述代码会生成一个独立的测试类TestBedTester(Unix/Linux)。可以用这个类来测试,但是不必在发布的产品中包含它,在将产品打包前删去这个测试类。

从多层嵌套类中访问外部类的成员
一个内部类即使被嵌套多层,它也能透明地访问所有它所嵌入的外围类的所有成员。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

《Java编程思想》第四版之内部类学习之(二)——匿名内部类

引言:内部类,即将一个类的定义放在另一个类的定义内部。内部类与组合是完全不同的概念。内部类看似是一种代码的隐藏机制,其实,它能够了解外部类,并且与之通信,这为我们的编程提供了极大的方便。 4内部类与向...

《Java编程思想》第四版之内部类学习之(四)——内部类进阶

19内部类的继承 110内部类可以被覆盖吗 111局部内部类 112内部类标识符 113总结 在内部类章节中,我们了解到了一个普通内部类必须要通过外部类对象来创建,并且它会获得一个外部类对象的引用,这...

Java编程思想第四版第七章学习(1)——基类初始化

复用类有两种方法,如下所示。 1、第一种方法:在新类产生现有类的对象,称为组合,该方法是复用了现有程序代码的 功能,而不是它的形式。 编译器不会为每一个引用都创建默认对象,如果要初...
  • Muc_hui
  • Muc_hui
  • 2016年05月18日 15:26
  • 424

Java编程思想第四版第十二章学习——通过异常处理错误(1)

使用异常带来的好处: 它降低了错误处理代码的复杂度。使用异常后,不需要检查特定的错误并在程序中的许多地方去处理它。因为异常机制将保证能够捕获这个错误且只需在一个地方处理错误,即异常处理程序中。 ...
  • Muc_hui
  • Muc_hui
  • 2016年07月12日 19:42
  • 429

Java编程思想第四版第十二章学习——通过异常处理错误(2)

1.Java异常标准Throwable类用来表示任何可以作为异常被抛出的类。Throwable对象可以分为两类:Error用来表示编译时和系统错误(一般无需关心),Exception是可以被抛出的基本...
  • Muc_hui
  • Muc_hui
  • 2016年07月13日 13:11
  • 242

Java编程思想第四版第八章学习——多态

在面向对象的程序设计语言中,多态是继数据抽象和继承之后的第三种基本特征。使用多态可以改善代码的组织结构和可读性,重要的是可以创建可扩展的程序。 所谓多态,就是把不同的子类对象都当做父类来看,可以屏...
  • Muc_hui
  • Muc_hui
  • 2016年05月19日 16:31
  • 241

《Java编程思想》第四版之内部类学习之(一)——简单使用

版权声明:学习内容均为本人笔记,代码均为本人依据课本所写或改编,笔记均为个人心得或书中摘抄 引言:内部类,即将一个类的定义放在另一个类的定义内部。内部类与组合是完全不同的概念。内部类看似是一种代码的...

Java编程思想第四版第九章学习——接口

1、抽象类包含抽象方法的类叫做抽象类。如果一个类包含一个或多个抽象方法,该类必须被限定为抽象的。创建抽象类和抽象方法的好处是可以使类的抽象性明确起来,并告诉用户和编译器打算如何来使用它们。 抽象类还...
  • Muc_hui
  • Muc_hui
  • 2016年05月27日 15:25
  • 567

Java编程思想第四版第五章学习 ——方法重载

这仅作为个人学习中认为容易忽视或者比较重要的内容。每个人的能力和关注点不同,可能我这说的还是很low。希望大家多多包涵。 注意点: 1.重载方法时,如果传入的数据类型(实际参数类型)小于方法中声明...
  • Muc_hui
  • Muc_hui
  • 2016年05月09日 23:19
  • 437

Java编程思想第四版第十一章学习——持有对象

持有对象
  • Muc_hui
  • Muc_hui
  • 2016年06月03日 21:42
  • 470
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java编程思想第四版第十章学习——内部类(1)
举报原因:
原因补充:

(最多只允许输入30个字)