java基础-嵌套类
2016-11-13 16:16
155 查看
在何处使用嵌套类
顾名思义,嵌套类(或内部类) 是在一个类中定义的另一个类。public、
private或
protected。在想要以面向对象的方式执行类中的内部处理工作时,嵌套类可能很有用,但此功能仅限于需要它的类。
通常,在需要一个与定义它的类紧密耦合的类时,应该使用嵌套类。嵌套类能够访问包含它的类中的私有数据,但此结构会带来负面影响,这些影响在开始使用嵌套(或内部)类时并不明显。
嵌套类中的范围
因为嵌套类具有范围,所以它受范围规则约束。例如,可通过该类的实例(对象)访问成员变量。嵌套类也是如此。假设一个
Manager和一个名为
DirectReports的嵌套类之间的关系为:后者是
Manager下属的
Employee的集合:
Manager对象表示唯一的人一样,
DirectReports对象表示一位经理下属的真实的人(员工)的集合。
DirectReports在不同
Manager中不同。在本例中,应该仅在包含
DirectReports嵌套类的
Manager实例中引用它,所以我将它声明为
private。
公共嵌套类
因为它是 private,所以只有
Manager可以创建
DirectReports实例。但是,假设您想为一个外部实体提供创建
DirectReports实例的能力。在这种情况下,似乎可为
DirectReports类提供
public范围,然后任何外部代码都可以创建
DirectReports实例,如清单
1 所示。
清单 1. 创建
DirectReports实例:第一次尝试
Manager中定义
DirectReports的方式,以及范围规则。
理解范围规则
如果您拥有 Manager的一个成员变量,您会认为编译器会要求您拥有
Manager对象的引用,然后才能引用它,对吧?
DirectReports也是如此,至少在 清单
1 中定义它时是这样。
要创建一个公共嵌套类的实例,需要使用
new运算符的一个特殊版本。结合对一个外部类的封闭实例的引用,可使用
new创建嵌套类的实例:
new关键字,后跟想要创建的类。
静态内部类
有时,您希望创建一个(在概念上)与另一个类紧密耦合的类,但范围规则比较宽松,不需要使用对封闭实例的引用。这时静态 内部类就可以派上用场。一个常见的示例是实现一个 Comparator,用它来比较同一个类的两个实例,通常用于对类进行排序:
ManagerComparator这样的实用程序类,没有必要创建外部类,而且它们可能让您的代码库变得杂乱。将这些类定义为静态内部类是一种解决办法。
匿名内部类
使用 Java 语言,可在任何地方实现抽象类和接口,如果必要,甚至可在一个方法内实现,而且无需为类提供名称。此功能实际上是一种编译器窍门,但有时拥有匿名内部类很方便。清单 2 是以 第 17 单元:接口 中的清单
1 中的示例为基础构建的,添加了一个处理不属于
StockOptionEligible的
Employee类型的默认方法。该清单首先提供了
HumanResourcesApplication中的一个处理库存选项的方法,然后提供了一个驱动该方法的
JUnit 测试:
清单 2. 处理不属于
StockOptionEligible的
Employee类型
StockOptionEligible的两个独立实现:一个用于
Employee,另一个用于
Person(以符合接口要求)。然后是一个
StockOptionProcessingCallback实现,用于处理
Manager实例的库存选项。
可能需要一定的时间才能掌握匿名内部类的概念,但它们非常方便。我一直在 Java 代码中使用它们。而且作为 Java 开发人员,随着您的不断进步,我相信您也会这么做。
测试您的理解情况
什么是嵌套类?一个向应用程序中的其他类提供某种工具的类
一个在另一个类中定义的类
将一个或多个接口引用传入其构造方法的类
上述选项都不是
何时可以使用嵌套类?
当需要定义一个与另一个类(在功能上)紧密耦合的类时
当希望编写一个使用来自 JDK 的大量接口的类时
当一个类需要访问另一个类的私有数据,而您已超出了应用程序允许的最大类数量时
对于一个定义了超过 20 个方法且应重构的类
您能否找到以下代码中的错误?选择最佳答案,解释您的选择,并提供正确的代码。
Outer不是合法的 Java 类名。
类名
Inner难以理解。
类
Outer中定义的 main 方法的方法签名是错误的。
main() 中的
log.info()调用了太多参数。
类
Inner的主体是空的。
上述选项都不是。
参阅问题 3 中的代码清单。假设您在包含
Outer的包中想要一个名为
AnotherOuter且可以实例化
Outer.Inner的新类。您需要对
Outer.Inner的声明执行哪些更改?
没必要执行更改;
Inner可按原样实例化。
没有内部类可包含它的类外部实例化。
将
Inner的可视性更改为
protected或包私有。
将
static修饰符添加到
Inner类声明中。
上述选项都不是。
给定以下框架,充实
main()方法来执行以下操作:
实例化
Hello类
调用
Hello的
talk()方法,向它传递一个实现为匿名内部类的
HelloCallback实例
修改
sayHello()的匿名内部类实现,以便使用
Hello上定义的
Logger来实现输出:
“This implementation says:”
whatToSay字符串
嵌套类与内部类有何区别?
内部类是仅使用私有访问级别定义的类,而嵌套类被声明为 static。
两个术语同义,可以交替使用。
嵌套类必须位于封闭类中,并在封闭类的任何变量之前声明。
嵌套类在 main() 中定义,而内部类可在任何地方定义。
不存在所谓的嵌套类。
上述选项都不是。
以下哪句有关内部类的描述是正确的?
内部类可访问包含它的类的任何私有数据变量,除非将它声明为
static。
内部类必须声明为
public,才能被封闭类以外的其他任何类实例化。
除非在特殊情况下,否则不允许使用静态内部类。
内部类对其封闭类完全不可见。
上述选项都不是。
答案:
什么是嵌套类?( b )
一个向应用程序中的其他类提供某种工具的类
一个在另一个类中定义的类
将一个或多个接口引用传入其构造方法的类
上述选项都不是
何时可以使用嵌套类?( a )
当需要定义一个与另一个类(在功能上)紧密耦合的类时
当希望编写一个使用来自 JDK 的大量接口的类时
当一个类需要访问另一个类的私有数据,而您已超出了应用程序允许的最大类数量时
对于一个定义了超过 20 个方法且应重构的类
您能否找到以下代码中的错误?选择最佳答案,解释您的选择,并提供正确的代码。( f )
package com.makotojava.intro.quiz; import java.util.logging.Logger; public class Outer { private static final Logger log = Logger.getLogger(Outer.class.getName()); public void setInner(Inner inner) { this.inner = inner; } private Inner inner; public Inner getInner() { return inner; } private class Inner { } public static void main(String[] args) { Outer outer = new Outer(); Inner inner = new Outer.Inner(); outer.setInner(inner); log.info("Outer/Inner: " + outer.hashCode() + "/" + outer.getInner().hashCode()); } }
类名
Outer不是合法的
Java 类名。
类名
Inner难以理解。
类
Outer中定义的
main 方法的方法签名是错误的。
main() 中的
log.info()调用了太多参数。
类
Inner的主体是空的。
上述选项都不是。
解释:代码行
Inner inner = new Outer.Inner();是有错误的。对于引用 一个封闭类去实例化一个嵌套类的语法是不正确的。它应该是:
Inner inner = outer.new Inner();
参阅问题 3 中的代码清单。假设您在包含
Outer的包中想要一个名为
AnotherOuter且可以实例化
Outer.Inner的新类。您需要对
Outer.Inner的声明执行哪些更改?(
c )
没必要执行更改;
Inner可按原样实例化。
没有内部类可包含它的类外部实例化。
将
Inner的可视性更改为
protected或包私有。
将
static修饰符添加到
Inner类声明中。
上述选项都不是。
给定以下框架,充实
main()方法来执行以下操作:
实例化
Hello类
调用
Hello的
talk()方法,向它传递一个实现为匿名内部类的
HelloCallback实例
修改
sayHello()的匿名内部类实现,以便使用
Hello上定义的
Logger来实现输出:
“This implementation says:”
whatToSay字符串
import java.util.logging.Logger; public class Hello { private static final Logger log = Logger.getLogger(Hello.class.getName()); interface HelloCallback { void sayHello(String whatToSay); } public void talk(HelloCallback helloCallback) { helloCallback.sayHello("Hello, world (how original :/)..."); } public static void main(String[] args) { Hello hello = new Hello(); hello.talk(new HelloCallback() { @Override public void sayHello(String whatToSay) { log.info("This implementation says: " + whatToSay); } }); } }
能否编写一个可由您应用程序中的任何类(无论它位于哪个包中)实例化的内部类,而无需外部类的封闭实例?解释您的答案。
答案:可以。内部类应该为修饰符
static声明,并且
为
public可见。然后在您应用程序的任何类都可以实例化内部类,无需外部类的
封闭实例。
嵌套类与内部类有何区别? ( b )
内部类是仅使用私有访问级别定义的类,而嵌套类被声明为 static。
两个术语同义,可以交替使用。
嵌套类必须位于封闭类中,并在封闭类的任何变量之前声明。
嵌套类在 main() 中定义,而内部类可在任何地方定义。
不存在所谓的嵌套类。
上述选项都不是。
以下哪句有关内部类的描述是正确的? ( a )
内部类可访问包含它的类的任何私有数据变量,除非将它声明为
static。
内部类必须声明为
public,才能被封闭类以外的其他任何类实例化。
除非在特殊情况下,否则不允许使用静态内部类。
内部类对其封闭类完全不可见。
上述选项都不是。
相关文章推荐
- (转)Java基础——嵌套类、内部类、匿名类
- Java基础复习:嵌套类和内部类
- Java基础知识学习笔记——嵌套类(Nested Classes)
- Java 101之线程基础
- 第二讲 Java语言基础知识
- Eclipse基础--java环境变量设置
- 学java也快半年了,一直在看基础的东西,终于决定开始转J2ee了……
- Java基础之关键字
- Java动画编程基础第一部分
- Java Swing入门基础 (转)
- Java Swing入门基础
- Java动画编程基础第二部分
- 基于Java的动画编程基础
- Java 应了解的基础知识(转载)
- (原创) 脚踏实地学Java之:基础篇
- 回复:学习java必须有c++基础么?
- JAVA调试技术--基础
- Java初学及基础问题
- JAVA面试基础试题[转贴]
- 原创:Java基础,参数配置,注意事项! jdk1.5+jsp+mysql+tomcat的配置