为什么匿名内部接口参数错误类只能访问常量参数

java中内部类_百度知道
java中内部类
java中创建内部类有哪些好处?怎么创建内部类啊,创建内部类的方法有哪些?希望各位大侠们不吝赐教,我是个菜鸟,刚学习java.
其他类似问题
按默认排序
其他5条回答
内部类可以直接调用内部类所在类的成员变量,直接把类定义在类的内部跟定义方法一样,如public class A{
void f(){}
void fun(){}
内部的类可以直接操作它外部的那个类的属性和方法这就是好处
就我自己的代码经验 首先可以肯定的是 我没有遇到过 任何 必须使用内部类的情况当然 我个人觉得 也不太会有 必须使用内部类的情况 (考试要求除外)我使用内部类的情况 好像...只有2种第一就是 这个内部类类 只为本类提供支持 其他任何类 任何方法 或者 任何代码 在任何情况下 都不会 不可能也不需要 使用到本内部类 , 那么我有可能会将它定义为内部类 当然也是为了分的更清楚 特别如果遇到 重载比较多的 为了方便区分 可以使用内部类第二种就是为了 封装 ,使用 匿名内部类 不让外部知道 为了保密性 不过这样也会相对增加代码的内聚 而相对使得耦合对降低当然 如果你懒到不想给这个方法取名字...也可以使用匿名内部类内部类的创建方法和一般类一样 只不过 一个是直接写在文件中 一个是写在某个已经定义的 class 的 {} 里面而已class outer{此处任意代码
class inner{
此处任意代码
}此处任意代码}
个人感觉唯一的作用就是搞Swing的时候用的上
static即静态类,只能在内部使用!
java的相关知识
等待您来回答
您可能关注的推广回答者:
下载知道APP
随时随地咨询
出门在外也不愁谈谈Java的匿名内部类 - 握住一缕风 - ITeye技术网站
博客分类:
在很多时候,我们需要在类的内部初始化一个静态的Map或者List,然后保存一下常量值提供给类内部方法使用。
我们通常的做法是:
首先初始化一个Map的静态变量。
然后在静态块添加常量值:
private final static Map&String, String& CONSTANT =
new HashMap&String, String&();
CONSTANT.put("1", "one");
CONSTANT.put("2", "two");
其实还可以这么写:
private final static Map&String, String& CONSTANT =
new HashMap&String, String&() {
put("1", "one");
put("2", "two");
如果对于这种方式比较陌生,那先看一个熟悉的:
new Thread() {
public void run() {
System.out.println("Thread running!");
}.start();
实际上上面这段代码的意思就是,声明一个Thread的子类并重写Thread的run()方法,然后创建一个该子类的实例然后调用其start()方法。由于声明的该Thread的子类没有名字,所以叫匿名类。又由于没有名字的类只能存在于一个类或者一个方法内部,所以又称为匿名内部类。
匿名内部类的语法也可以这么写:
Thread thread = new Thread() {
public void run() {
System.out.println("Thread running!");
thread.start();
唯一的区别就是不是直接创建子类并调用其方法,而是声明一个该子类的父类引用thread,然后通过该父类引用调用子类方法。
创建完匿名类的实例后,没有立即执行start(),创建实例和执行实例的方法分开。
两者的区别相当于:
new User().setName("Boyce Zhang");
User user = new User();
user.setName("Boyce Zhang");
匿名内部类的另一个语法场景:
new Thread() {
public void run() {
System.out.println("Thread running!");
实际上这种写法就是在匿名子类的类局部代码块中调用其类方法。
局部代码块内的语句是在创建该类的实例后由类加载器隐式立即执行的。
相当于:
public class MyThread extends Thread {
public void run() {
System.out.println("Thread running!");
所以三种方式在执行的时刻上略微的差别之外,效果并没有太大的区别。
这样一来,前面初始化Map的方式就不难理解了:
private final static Map&String, String& CONSTANT = new HashMap&String, String&() {
put("1", "one");
put("2", "two");
原理就是:
声明并实例化一个HashMap的子类(子类没有重写父类HashMap的任何方法),并且在子类的类局部代码块调用父类HashMap的put()方法。
最后声明一个Map接口引用CONSTANT指向实例化的HashMap子类的实例。
根据前面的例子我们知道,类局部代码块中的put()方法调用将在HashMap的匿名子类被实例化后由类加载器隐式的执行。
其实,对于Java的任何类或接口,都可以声明一个匿名类继承或实现它。如:
//重写父类方法,局部代码块调用自己重写过的父类方法。
List&String& list = new ArrayList&String&() {
public boolean add(String e) {
System.out.println("Cannot add anything!");
//代码块的顺序在前后都无所谓,可以出现在类范围的任何位置。
add("Boyce Zhang");
//局部代码块调用父类方法。
dao.add(new User(){
setName("Boyce Zhang");
setAge(26);
//重写父类方法
ThreadLocal&User& threadLocal = new ThreadLocal&User&() {
protected String initialValue() {
return new User("Boyce Zhang", 26);
在匿名类的内部我们不但可以实现或重写其父类的方法。
而且也可以在其类的局部代码块中执行自己的方法或者其父类的方法。
这并不是匿名内部类的特殊语法,而是Java的语法,对于任何类都适用。
这种写法常常就是用在实例化一个类后立即执行某些方法做一些类实例的数据初始化什么的。
其作用和先实例化一个类,在使用其引用调用需要立即调用的方法是一样的,如:
Map&String, String& map = new HashMap&String, String&();
map.put("1", "one");
map.put("2", "two");
这种语法的优点就是简单,实例化一个类后立即做一些事情,比较方便。
效果有一点儿像Javascript里的即时函数一样。但是有本质的区别。
因为Javascript没有类的概念,或者说Javascript中function就是类,类就是function,所以即时函数是加载完后执行整个function。而Java的局部代码块是可以选择执行类的任何方法。
当然这种写法也有其缺点:
每一个内部类的实例都会隐性的持有一个指向外部类的引用(静态内部类除外),这样一方面是多余的引用浪费,另一方面当串行化这个子类实例时外部类也会被不知不觉的串行化,如果外部类没有实现serialize接口时,就会报错。
该用户名已经存在
浏览: 26468 次
来自: 上海
Mapper类?
mit(),怎么执行啊?
可以使用spring的动态数据源
已经封装好了。还有处理机制。。
panduozhi 写道请教个问题 ...trackbacks-0
重点理解Java引入内部类的原因以及好处
内部类能让你再逻辑上将相互从属的类组织起来,并且在类的内部控制访问权限。但是切记,内部类和合成时截然不同的,这一点非常重要。
几个有代表性的代码块
接口可以嵌套在类或其它接口中
接口的嵌套
&&1package&edu.bupt.innerclass2;
&&3class&A&{
&&4&&&&&&interface&B&{
&&5&&&&&&&&void&f();
&&6&&&&&&}
&&7&&&&&&public&class&BImp&implements&B&{
&&8&&&&&&&&public&void&f()&{}
&&9&&&&&&}
&10&&&&&&private&class&BImp2&implements&B&{
&11&&&&&&&&public&void&f()&{}
&12&&&&&&}
&13&&&&&&public&interface&C&{
&14&&&&&&&&void&f();
&15&&&&&&}
&16&&&&&&class&CImp&implements&C&{
&17&&&&&&&&public&void&f()&{}
&18&&&&&&}
&19&&&&&&private&class&CImp2&implements&C&{
&20&&&&&&&&public&void&f()&{}
&21&&&&&&}
&22&&&&&&private&interface&D&{
&23&&&&&&&&void&f();
&24&&&&&&}
&25&&&&&&private&class&DImp&implements&D&{
&26&&&&&&&&public&void&f()&{}
&27&&&&&&}
&28&&&&&&public&class&DImp2&implements&D&{
&29&&&&&&&&public&void&f()&{}
&30&&&&&&}
&31&&&&&&public&D&getD()&{&return&new&DImp2();&}
&32&&&&&&private&D&dR
&33&&&&&&public&void&receiveD(D&d)&{
&34&&&&&&&&dRef&=&d;
&35&&&&&&&&dRef.f();
&36&&&&&&}
&39&&&&interface&E&{
&40&&&&&&interface&G&{
&41&&&&&&&&void&f();
&42&&&&&&}
&43&&&&&&//&Redundant&"public":
&44&&&&&&public&interface&H&{
&45&&&&&&&&void&f();
&46&&&&&&}
&47&&&&&&void&g();
&48&&&&&&//&Cannot&be&private&within&an&interface:
&49&&&&&&//!&private&interface&I&{}
&52&&&&public&class&NestingInterface&{
&53&&&&&&//B在A中定义的为默认级别
&54&&&&&&public&class&BImp&implements&A.B&{
&55&&&&&&&&//public&static&int&a;
&56&&&&&&&&public&void&f()&{}
&57&&&&&&}
&59&&&&&&//这个内部类是编译不过的
&60&&&&&&/**//*
&61&&&&&&&*&No&enclosing&instance&of&type&A&is&accessible&to&invoke&the&super&constructor.&
&62&Must&define&a&constructor&and&explicitly&qualify&its&super&constructor&
&63&invocation&with&an&instance&of&A&(e.g.&x.super()&where&x&is&an&instance&of&A).
&64&&&&&&&*/
&65&&&&&&public&class&BImpExtends&extends&A.BImp{
&67&&&&&&}
&68&&&&&&public&class&BImpExtendsCopy&extends&A.BImp{
&69&&&&&&&&&&public&BImpExtendsCopy(A&a){
&70&&&&&&&&&&&&&&a.super();
&71&&&&&&&&&&}
&72&&&&&&}
&73&&&&&&class&CImp&implements&A.C&{
&74&&&&&&&&public&void&f()&{}
&75&&&&&&}
&76&&&&&&//&Cannot&implement&a&private&interface&except
&77&&&&&&//&within&that&interface's&defining&class:
&78&&&&&&//!&class&DImp&implements&A.D&{
&79&&&&&&//!&&public&void&f()&{}
&80&&&&&&//!&}
&81&&&&&&class&EImp&implements&E&{
&82&&&&&&&&public&void&g()&{}
&83&&&&&&}
&84&&&&&&class&EGImp&implements&E.G&{
&85&&&&&&&&public&void&f()&{}
&86&&&&&&}
&87&&&&&&class&EImp2&implements&E&{
&88&&&&&&&&public&void&g()&{}
&89&&&&&&&&class&EG&implements&E.G&{
&90&&&&&&&&&&public&void&f()&{}
&91&&&&&&&&}
&92&&&&&&}
&93&&&&&&public&static&void&main(String[]&args)&{
&94&&&&&&&&A&a&=&new&A();
&95&&&&&&&&//&Can't&access&A.D:
&96&&&&&&&&//&A.D&ad&=&a.getD();
&97&&&&&&&&//&Doesn't&return&anything&but&A.D:
&98&&&&&&&&&//A.DImp2&di1=a.getD();
&99&&&&&&&&&A.DImp2&di2&=&(A.DImp2)a.getD();
<span style="color: #0&&&&&&&&&di2.f();
<span style="color: #1&&&&&&&&&
<span style="color: #2&&&&&&&&//&Cannot&access&a&member&of&the&interface:
<span style="color: #3&&&&&&&&//!&a.getD().f();
<span style="color: #4&&&&&&&&&//a.getD().f();
<span style="color: #5&&&&&&&&//&Only&another&A&can&do&anything&with&getD():
<span style="color: #6&&&&&&&&A&a2&=&new&A();
<span style="color: #7&&&&&&&&a2.receiveD(a.getD());
<span style="color: #8&&&&&&}
<span style="color: #9&&&&}
<span style="color: #0
返回内部类引用
&1//:&c08:Parcel2.java
&2//&Returning&a&reference&to&an&inner&class.
&4public&class&Parcel2&{
&5&&class&Contents&{
&6&&&&private&int&i&=&<span style="color: #;
&7&&&&public&int&value()&{&return&i;&}
&9&&class&Destination&{
<span style="color: #&&&&private&String&
<span style="color: #&&&&Destination(String&whereTo)&{
<span style="color: #&&&&&&label&=&whereTo;
<span style="color: #&&&&}
<span style="color: #&&&&String&readLabel()&{&return&&}
<span style="color: #&&}
<span style="color: #&&public&Destination&to(String&s)&{
<span style="color: #&&&&return&new&Destination(s);
<span style="color: #&&}
<span style="color: #&&public&Contents&cont()&{
<span style="color: #&&&&return&new&Contents();
<span style="color: #&&}
<span style="color: #&&public&void&ship(String&dest)&{
<span style="color: #&&&&Contents&c&=&cont();
<span style="color: #&&&&Destination&d&=&to(dest);
<span style="color: #&&&&System.out.println(d.readLabel());
<span style="color: #&&}
<span style="color: #&&public&static&void&main(String[]&args)&{
<span style="color: #&&&&Parcel2&p&=&new&Parcel2();
<span style="color: #&&&&p.ship("Tanzania");
<span style="color: #&&&&Parcel2&q&=&new&Parcel2();
<span style="color: #&&&&//&Defining&references&to&inner&classes:
<span style="color: #&&&&Parcel2.Contents&c&=&q.cont();
<span style="color: #&&&&Parcel2.Destination&d&=&q.to("Borneo");
<span style="color: #&&}
<span style="color: #}&///:~
<span style="color: #
<span style="color: #除非是在"宿主类(outer&class)"的非static方法里面,否则无论你再哪里创建内部类的对象,都必须OuterClassName.InnerClassName的形式来表示这个对象的类型,就像在main()里面那样
内部类在隐藏实现方面的作用
内部类隐藏机制
&2但是,当你将它上转到基类时,特别是interface的时候,就会发现,内部类还是有它自己的特性的。这样,任何人都不能看到或者访问到内部类了--也就是interface的实现了,于是&#8220;隐藏实现&#8221;就轻而易举了。你所得到的只是一个基类或者interface的reference。
&3当你拿到基类或interface的reference的时候,有可能你会没办法找出它的具体类型。
&4如下所示
&5package&edu.b.innerclass2;
&6//在类中定义的内部类 内部类可以是private&protected&public但是要注意其使用
&7class&Parcel3&{
&9&&&&private&class&PContents&implements&Contents{
<span style="color: #&&&&&&&&private&int&i=<span style="color: #;
<span style="color: #&&&&&&&&public&int&value(){
<span style="color: #&&&&&&&&&&&&return&i;
<span style="color: #&&&&&&&&}
<span style="color: #&&&&}
<span style="color: #&&&&
<span style="color: #&&&&class&PDestination&implements&Destination{
<span style="color: #&&&&&&&&private&String&
<span style="color: #&&&&&&&&public&PDestination(){
<span style="color: #&&&&&&&&&&&&
<span style="color: #&&&&&&&&}
<span style="color: #&&&&&&&&private&PDestination(String&whereTo){
<span style="color: #&&&&&&&&&&&&label=whereTo;
<span style="color: #&&&&&&&&}
<span style="color: #&&&&&&&&public&String&readLabel(){
<span style="color: #&&&&&&&&&&&&return&
<span style="color: #&&&&&&&&}
<span style="color: #&&&&}
<span style="color: #&&&&
<span style="color: #&&&&public&Contents&cont(){
<span style="color: #&&&&&&&&return&new&PContents();
<span style="color: #&&&&}
<span style="color: #&&&&
<span style="color: #&&&&public&Destination&dest(String&s){
<span style="color: #&&&&&&&&return&new&PDestination(s);
<span style="color: #&&&&}
<span style="color: #
<span style="color: #}
<span style="color: #
<span style="color: #
<span style="color: #public&class&TestParcel&{
<span style="color: #&&public&static&void&main(String[]&args)&{
<span style="color: #&&&&Parcel3&p&=&new&Parcel3();
<span style="color: #&&&&Contents&c&=&p.cont();
<span style="color: #&&&&Destination&d&=&p.dest("Tanzania");
<span style="color: #&&&&//&Illegal&--&can't&access&private&class:
<span style="color: #&&&&//!&Parcel3.PContents&pc&=&p.new&PContents();
<span style="color: #&&}
<span style="color: #}&///:~
<span style="color: #在这个例子里,main()必须在另一个类里,这样才能让人看到内部类PContents的私密性方面的效果。
<span style="color: #Parcel3加了点新东西:内部类PContent是private的,所有除了Parcel3,谁都不能访问它。PDestination是protected的,因此除了Parcel3,同属这个package的类(因为protected也会给予包级权限),以及Parcel3的继承类,谁都不能访问PDestination。这就是说,客户程序员对这些成员的了解和访问权限是由限制的。实际上,你甚至不能将对象下转给private的内部类(或者是protected的内部类,除非你继承了这个类),因为,正如class&TestParcel所演示的,你根本就不能用这个名字。由此&#8220;private的内部类&#8221;为类的设计者们提供了一种&#8220;能彻底杜绝【用具体类型来编程所引起的依赖性问题type-coding&dependencies】,并且完全将实现细节隐藏起来&#8221;的方法&。此外,从客户程序员的角度来看,扩展interface也是毫无意义的,因为他根本没法访问public&interface以外的方法。
<span style="color: #普通类(非内部类)是不能被定义成private或protected的;它们只可能是public&或package权限的
匿名内部类的几种使用形式
A class defined within a method 在方法的内部定义一个类
A class defined within a scope inside a method 在方法的某个作用域里定义一个类
An anonymous class implementing an interface 一个实现了某个接口的匿名类
An anonymous class extending a class that has a nondefault constructor 一个继承了&#8220;某个有着非默认构造函数&#8221;的类匿名类
An anonymous class that performs field initialization一个进行数据成员初始化的匿名类
An anonymous class that performs construction using instance initialization (anonymous inner classes cannot have constructors)一个通过实例初始化(匿名内部类不能有构造函数)来进行构建的匿名类
某个有着非默认构造函
&1//:&c08:Wrapping.java
&2public&class&Wrapping&{
&3&&private&int&i;
&4&&public&Wrapping(int&x)&{&i&=&x;&}
&5&&public&int&value()&{&return&i;&}
&8//&An&anonymous&inner&class&that&calls
&9//&the&base-class&constructor.
<span style="color: #
<span style="color: #public&class&Parcel7&{
<span style="color: #&&public&Wrapping&wrap(int&x)&{
<span style="color: #&&&&//&Base&constructor&call:
<span style="color: #&&&&return&new&Wrapping(x)&{&//&Pass&constructor&argument.
<span style="color: #&&&&&&public&int&value()&{
<span style="color: #&&&&&&&&return&super.value()&*&<span style="color: #;
<span style="color: #&&&&&&}
<span style="color: #&&&&};&//&Semicolon&required
<span style="color: #&&}
<span style="color: #&&public&static&void&main(String[]&args)&{
<span style="color: #&&&&Parcel7&p&=&new&Parcel7();
<span style="color: #&&&&Wrapping&w&=&p.wrap(<span style="color: #);
<span style="color: #&&}
<span style="color: #}&///:~
对数据成员进行初始化的匿名类
&1//&An&anonymous&inner&class&that&performs
&2//&initialization.&A&briefer&version&of&Parcel4.java.
&4public&class&Parcel8&{
&5&&//&Argument&must&be&final&to&use&inside
&6&&//&anonymous&inner&class:
&&&&&&&&&&&& 如果定义一个匿名内部类,并且希望它使用一个在其外部定义的对象,那么编译会要求其参数引用是final的,就像dest()的参数一样,否则不是final的,将会得到一个编译时错误信息
&7&&public&Destination&dest(final&String&dest)&{
&8&&&&return&new&Destination()&{
&9&&&&&&&&& private&String&label&=&
<span style="color: #&&&&&&public&String&readLabel()&{&return&&}
<span style="color: #&&&&};
<span style="color: #&&}
<span style="color: #&&public&static&void&main(String[]&args)&{
<span style="color: #&&&&Parcel8&p&=&new&Parcel8();
<span style="color: #&&&&Destination&d&=&p.dest("Tanzania");
<span style="color: #&&}
<span style="color: #}&///:~
实例初始化来构建匿名内部类
//:&c08:AnonymousConstructor.java
//&Creating&a&constructor&for&an&anonymous&inner&class.
import&com.bruceeckel.simpletest.*;
abstract&class&Base&{
&&public&Base(int&i)&{
&&&&System.out.println("Base&constructor,&i&=&"&+&i);
&&public&abstract&void&f();
public&class&AnonymousConstructor&{
&&private&static&Test&monitor&=&new&Test();
&&public&static&Base&getBase(int&i)&{
&&&&return&new&Base(i)&{
&&&&&&&&System.out.println("Inside&instance&initializer");
&&&&&&public&void&f()&{
&&&&&&&&System.out.println("In&anonymous&f()");
&&public&static&void&main(String[]&args)&{
&&&&Base&base&=&getBase(<span style="color: #);
&&&&base.f();
&&&&monitor.expect(new&String[]&{
&&&&&&"Base&constructor,&i&=&47",
&&&&&&"Inside&instance&initializer",
&&&&&&"In&anonymous&f()"
In&this&case,&the&variable&i&did&not&have&to&be&final.&While&i&is&passed&to&the&base&constructor&of&the&anonymous&class,&it&is&never&directly&used&inside&the&anonymous&class.&
实例初始化来构建的匿名内部类
&1//&Using&"instance&initialization"&to&perform
&2//&construction&on&an&anonymous&inner&class.
&4public&class&Parcel9&{
&5&&private&static&Test&monitor&=&new&Test();
&6&&public&Destination
&7&&dest(final&String&dest,&final&float&price)&{
&8&&&&return&new&Destination()&{
&9&&&&&&private&int&
<span style="color: #&&&&&&//&Instance&initialization&for&each&object:
<span style="color: #&&&&&&{
<span style="color: #&&&&&&&&cost&=&Math.round(price);
<span style="color: #&&&&&&&&if(cost&&&<span style="color: #0)
<span style="color: #&&&&&&&&&&System.out.println("Over&budget!");
<span style="color: #&&&&&&}
<span style="color: #&&&&&&private&String&label&=&
<span style="color: #&&&&&&public&String&readLabel()&{&return&&}
<span style="color: #&&&&};
<span style="color: #&&}
<span style="color: #&&public&static&void&main(String[]&args)&{
<span style="color: #&&&&Parcel9&p&=&new&Parcel9();
<span style="color: #&&&&Destination&d&=&p.dest("Tanzania",&<span style="color: #1.395F);
<span style="color: #&&&&monitor.expect(new&String[]&{
<span style="color: #&&&&&&"Over&budget!"
<span style="color: #&&&&});
<span style="color: #&&}
<span style="color: #}&///:~
内部类与宿主类的关系
上面讲的内部类还只是一种隐藏名字和组织代码的方式,但是内部类还有一种用法。如果你创建了一个内部类,那么这个内部类的对象,就与创建它的&#8220;宿主类的对象(enclosing object)&#8221;产生了某种联系,这样它就能访问宿主类对象的成员了---不需要任何特别的授权。此外,内部类还能访问宿主类的所有元素。
内部类访问宿主类的成员
&1package&edu.bupt.innerclass2;
&3interface&Selector&{
&4&&&&boolean&end();
&6&&&&Object&current();
&8&&&&void&next();
<span style="color: #public&class&Sequence&{
<span style="color: #&&&&private&Object[]&
<span style="color: #
<span style="color: #&&&&private&int&next&=&<span style="color: #;
<span style="color: #
<span style="color: #&&&&public&Sequence(int&size)&{
<span style="color: #&&&&&&&&objects&=&new&Object[size];
<span style="color: #&&&&}
<span style="color: #&&&&public&void&add(Object&x)&{
<span style="color: #&&&&&&&&if&(next&&&objects.length)
<span style="color: #&&&&&&&&&&&&objects[next++]&=&x;
<span style="color: #&&&&}
<span style="color: #&&&&private&class&SSelector&implements&Selector&{
<span style="color: #&&&&&&&&private&int&i&=&<span style="color: #;
<span style="color: #
<span style="color: #&&&&&&&&public&boolean&end()&{
&&&&&&&&&&&&&&&&&&& //return i == Sequence.this.objects.
&&&// 在内部类中使用Sequence.this, 内部类对象中所指向宿主类的对象的reference
<span style="color: #&&&&&&&&&&&&return&i&==&objects.
<span style="color: #&&&&&&&&}
<span style="color: #&&&&&&&&public&Object&current()&{
<span style="color: #&&&&&&&&&&&&return&objects[i];
<span style="color: #&&&&&&&&}
<span style="color: #&&&&&&&&public&void&next()&{
<span style="color: #&&&&&&&&&&&&if&(i&&&objects.length)
<span style="color: #&&&&&&&&&&&&&&&&i++;
<span style="color: #&&&&&&&&}
<span style="color: #&&&&}
42&&&&public&Selector&getSelector()&{
43&&&&&&&&return&new&SSelector();
<span style="color: #&&&&public&static&void&main(String[]&args)&{
<span style="color: #&&&&&&&&Sequence&sequence&=&new&Sequence(<span style="color: #);
<span style="color: #&&&&&&&&for&(int&i&=&<span style="color: #;&i&&&<span style="color: #;&i++)
<span style="color: #&&&&&&&&&&&&sequence.add(Integer.toString(i));
<span style="color: #&&&&&&&&Selector&selector&=&sequence.getSelector();
<span style="color: #&&&&&&&&while&(!selector.end())&{
<span style="color: #&&&&&&&&&&&&System.out.println(selector.current());
<span style="color: #&&&&&&&&&&&&selector.next();
<span style="color: #&&&&&&&&}
<span style="color: #&&&&}
<span style="color: #}
<span style="color: #
内部类里肯定会有一个指向&#8220;要负责创建它的&#8221;宿主类对象的reference。这样,当你引用宿主类的成员的时候,就会使用那儿(隐蔽的)reference来选取成员。编译器会为你打理着一切,但是你还是应该知道,内部类对象的创建时与宿主类对象有关的。创建内部类对象的前提就是要获得宿主类对象的reference,如果编译器得不到这个引用,它就会报错,绝对大多数情况下,这个过程无需程序员的干预。最好的方式就是通过在宿主类里的非static方法里定一个getInnerClassName(){new InnerClassName();}
在宿主类static方法及宿主类外定义内部类的对象
&1//&Creating&instances&of&inner&classes.
&3public&class&Parcel11&{
&4&&class&Contents&{
&5&&&&private&int&i&=&<span style="color: #;
&6&&&&public&int&value()&{&return&i;&}
&8&&class&Destination&{
&9&&&&private&String&
<span style="color: #&&&&Destination(String&whereTo)&{&label&=&whereTo;&}
<span style="color: #&&&&String&readLabel()&{&return&&}
<span style="color: #&&}
<span style="color: #&&public&static&void&main(String[]&args)&{
<span style="color: #&&&&Parcel11&p&=&new&Parcel11();
<span style="color: #&&&&//&Must&use&instance&of&outer&class
<span style="color: #&&&&//&to&create&an&instances&of&the&inner&class:
<span style="color: #&&&&Parcel11.Contents&c&=&p.new&Contents();
<span style="color: #&&&&Parcel11.Destination&d&=&p.new&Destination("Tanzania");
&&&&&&&&&&& //但是如果创建的是嵌套类static innerclass的对象的话,就不需要宿主类对象的reference了
<span style="color: #&&}
<span style="color: #}&///:~
Java嵌套类(static 内部类)和普通内部类的区别
如果你不需要这种&#8220;内部类对象和宿主类对象之间的&#8221;联系,那么你可以吧内部类定义为static的,这通常被称作&#8220;嵌套类nested class"。要想理解static用于内部类时的意思,你就必须记住,普通的内部类对象都默认保存&#8220;它的宿主类对象,也就是创建它的那个对象的reference。但是将内部类声明为static的时候,情况就不是这样了。嵌套类的意思是:
1,无需宿主类的对象就能创建嵌套类的对象。
2,不能在嵌套类的对象里面访问非static的宿主类对象
此外,嵌套类同普通的内部类还有一点不同。普通内部类的成员数据和方法只能到类的外围这一层,因此普通的内部类不能有static数据,static数据成员或嵌套类。但是这些东西static 嵌套类里都可以有。
但是如果创建的是嵌套类static innerclass的对象的话,就不需要宿主类对象的reference了
局部内部类
前面提到过,可以在代码块里创建内部类,典型的方式是在一个方法体的里面创建,局部内部类不能有访问说明符,因为它不是外围类的一部分;但是它可以访问当前代码块内的常量final定义的.以及宿主类的所有成员。
局部内部类
&1package&
&3import&java.util.LinkedL
&5interface&Counter&{
&6&&&&int&next();
&9public&class&LocalInnerClass&{
<span style="color: #&&&&private&int&count&=&<span style="color: #;
<span style="color: #
<span style="color: #&&&&Counter&getCounter(final&String&name)&{
<span style="color: #
14&&&&&&&&//&必须定义为final的,否则内部类中不能访问
15&&&&&&&&final&String&stringLocal&=&
<span style="color: #&&&&&&&&
<span style="color: #&&&&&&&&//&A&local&inner&class
<span style="color: #&&&&&&&&//&Illegal&modifier&for&the&local&class&LocalC&only&abstract&or
19&&&&&&&&//&final&is&permitted
20&&&&&&&&//LocalCounter的class的修饰符不能定义为private,protected,public
<span style="color: #&&&&&&&&class&LocalCounter&implements&Counter&{
<span style="color: #
<span style="color: #&&&&&&&&&&&&String&test&=&stringL
<span style="color: #&&&&&&&&&&&&
<span style="color: #&&&&&&&&&&&&//The&field&staticVariable&cannot&be&declared&&static&fields&can&only&be&declared&in&static&or&top&
26&&&&&&&&&&&&//level&types
27&&&&&&&&&&&&//static&String&staticVariable="";
<span style="color: #
<span style="color: #&&&&&&&&&&&&public&LocalCounter()&{
<span style="color: #&&&&&&&&&&&&&&&&//&Local&inner&class&can&have&a&constructor
<span style="color: #&&&&&&&&&&&&&&&&System.out.println("LocalCounter()");
<span style="color: #&&&&&&&&&&&&}
<span style="color: #
<span style="color: #&&&&&&&&&&&&public&int&next()&{
<span style="color: #&&&&&&&&&&&&&&&&//&Cannot&refer&to&a&non-final&variable&methodLocal&inside&an
<span style="color: #&&&&&&&&&&&&&&&&//&inner&class&defined&in&a&different&method
<span style="color: #&&&&&&&&&&&&&&&&System.out.println(stringLocal);
<span style="color: #&&&&&&&&&&&&&&&&System.out.print(name);//&access&local&final,must&be&final
39&&&&&&&&&&&&&&&&return&count++;&//&访问宿主类的成员
40&&&&&&&&&&&&&&&&//&return&LocalInnerClass.this.count++;
<span style="color: #&&&&&&&&&&&&}
<span style="color: #&&&&&&&&}
<span style="color: #&&&&&&&&
<span style="color: #&&&&&&&&return&new&LocalCounter();
<span style="color: #&&&&}
<span style="color: #
<span style="color: #&&&&//&The&same&thing&happens&in&the&anoymous&inner&class
<span style="color: #&&&&Counter&getCounter2(final&String&name)&{
<span style="color: #&&&&&&&&//&必须定义为final的,否则内部类中不能访问
<span style="color: #&&&&&&&&final&String&localString&=&"ddd";
<span style="color: #
<span style="color: #&&&&&&&&return&new&Counter()&{
<span style="color: #&&&&&&&&&&&&String&
<span style="color: #&&&&&&&&&&&&//&Anonymous&inner&class&cannot&have&a&named
<span style="color: #&&&&&&&&&&&&//&construtor,only&an&instance&initializer:
<span style="color: #&&&&&&&&&&&&{
<span style="color: #&&&&&&&&&&&&&&&&//&Cannot&refer&to&a&non-final&variable&localString&inside&an
<span style="color: #&&&&&&&&&&&&&&&&//&inner&class&defined&in&a&different&method
<span style="color: #&&&&&&&&&&&&&&&&System.out.println(localString);
<span style="color: #&&&&&&&&&&&&&&&&System.out.println("Counter()");
<span style="color: #&&&&&&&&&&&&}
<span style="color: #
<span style="color: #&&&&&&&&&&&&public&int&next()&{
<span style="color: #&&&&&&&&&&&&&&&&System.out.print(name);//&access&local&final
<span style="color: #&&&&&&&&&&&&&&&&return&count++;
<span style="color: #&&&&&&&&&&&&}
<span style="color: #&&&&&&&&};
<span style="color: #&&&&}
<span style="color: #
<span style="color: #&&&&public&static&void&main(String[]&args)&{
<span style="color: #&&&&&&&&LocalInnerClass&lic&=&new&LocalInnerClass();
<span style="color: #&&&&&&&&Counter&c1&=&lic.getCounter("Local&inner"),&c2&=&lic
<span style="color: #&&&&&&&&&&&&&&&&.getCounter2("Annoumous&inner");
<span style="color: #
<span style="color: #&&&&&&&&for&(int&i&=&<span style="color: #;&i&&&<span style="color: #;&i++)
<span style="color: #&&&&&&&&&&&&System.out.println(c1.next());
<span style="color: #&&&&&&&&for&(int&i&=&<span style="color: #;&i&&&<span style="color: #;&i++)
<span style="color: #&&&&&&&&&&&&System.out.println(c2.next());
<span style="color: #
<span style="color: #&&&&}
<span style="color: #
<span style="color: #}
<span style="color: #
继承内部类
如下,可以看到InheritInner继承的只是内部类,而不是它的宿主类。但是等到要创建构造函数的时候,默认的构造函数玩不转了,你必须传给他宿主类对象的reference。此外,你还必须在构造函数里面使用这种语法 enclosingClassReference.super();
继承内部类
&1Inheriting&from&inner&classes
&3Because&the&inner&class&constructor&must&attach&to&a&reference&of&the&enclosing&class&object,&things&are&slightly&complicated&when&you&inherit&from&an&inner&class.&The&problem&is&that&the&&#8220;secret&#8221;&reference&to&the&enclosing&class&object&must&be&initialized,&and&yet&in&the&derived&class&there&#8217;s&no&longer&a&default&object&to&attach&to.&The&answer&is&to&use&a&syntax&provided&to&make&the&association&explicit:&Feedback
&6//:&c08:InheritInner.java
&7//&Inheriting&an&inner&class.
&9class&WithInner&{
<span style="color: #&&class&Inner&{}
<span style="color: #}
<span style="color: #
<span style="color: #public&class&InheritInner&extends&WithInner.Inner&{
<span style="color: #&&//!&InheritInner()&{}&//&Won't&compile
<span style="color: #&&InheritInner(WithInner&wi)&{
<span style="color: #&&&&wi.super();
<span style="color: #&&}
<span style="color: #&&public&static&void&main(String[]&args)&{
<span style="color: #&&&&WithInner&wi&=&new&WithInner();
<span style="color: #&&&&InheritInner&ii&=&new&InheritInner(wi);
<span style="color: #&&}
<span style="color: #}&///:~
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #You&can&see&that&InheritInner&is&extending&only&the&inner&class,&not&the&outer&one.&But&when&it&comes&time&to&create&a&constructor,&the&default&one&is&no&good,&and&you&can&#8217;t&just&pass&a&reference&to&an&enclosing&object.&In&addition,&you&must&use&the&syntax&Feedback
<span style="color: #
<span style="color: #
<span style="color: #enclosingClassReference.super();
<span style="color: #
为什么要使用内部类
在一定程度上解决Java中多重继承的问题
内部类解决多重继承问题
&1//:&c08:MultiInterfaces.java
&2//&Two&ways&that&a&class&can&implement&multiple&interfaces.
&4interface&A&{}
&5interface&B&{}
&7class&X&implements&A,&B&{}
&9class&Y&implements&A&{
<span style="color: #&&B&makeB()&{
<span style="color: #&&&&//&Anonymous&inner&class:
<span style="color: #&&&&return&new&B()&{};
<span style="color: #&&}
<span style="color: #}
<span style="color: #
<span style="color: #public&class&MultiInterfaces&{
<span style="color: #&&static&void&takesA(A&a)&{}
<span style="color: #&&static&void&takesB(B&b)&{}
<span style="color: #&&public&static&void&main(String[]&args)&{
<span style="color: #&&&&X&x&=&new&X();
<span style="color: #&&&&Y&y&=&new&Y();
<span style="color: #&&&&takesA(x);
<span style="color: #&&&&takesA(y);
<span style="color: #&&&&takesB(x);
<span style="color: #&&&&takesB(y.makeB());
<span style="color: #&&}
<span style="color: #}&///:~
<span style="color: #
<span style="color: #
<span style="color: #--------------------------------------------
但是如果你碰上的不是interface而是abstract类或实体类,而且还一定要同时实现这两个类的话,那么你只能使用内部类了:
<span style="color: #//:&c08:MultiImplementation.java
<span style="color: #//&With&concrete&or&abstract&classes,&inner
<span style="color: #//&classes&are&the&only&way&to&produce&the&effect
<span style="color: #//&of&"multiple&implementation&inheritance."
<span style="color: #package&c08;
<span style="color: #
<span style="color: #class&D&{}
<span style="color: #abstract&class&E&{}
<span style="color: #
<span style="color: #class&Z&extends&D&{
<span style="color: #&&E&makeE()&{&return&new&E()&{};&}
<span style="color: #}
<span style="color: #
<span style="color: #public&class&MultiImplementation&{
<span style="color: #&&static&void&takesD(D&d)&{}
<span style="color: #&&static&void&takesE(E&e)&{}
<span style="color: #&&public&static&void&main(String[]&args)&{
<span style="color: #&&&&Z&z&=&new&Z();
<span style="color: #&&&&takesD(z);
<span style="color: #&&&&takesE(z.makeE());
<span style="color: #&&}
<span style="color: #}&///:~
<span style="color: #
<span style="color: #
<span style="color: #
即使无需解决&#8221;多重实现的继承multiple implementation inheritance)"这类问题,那么即使没有内部类,你也完全可以解决问题。但是有了内部类,你就得到如下的附加特性:
1,内部类可以有多个实例,而每个又都可以有它自己的,与宿主类对象无关的状态信息
2,一个宿主类里可以放上好几个内部类,它们可以用各自不同的方式来实现同一个interface或继承同一个类。举例来说,要是Sequence.java没有使用内部类,那么牛就只能说"Sequence是一个Selector&#8221;,于是每个Sequence里面就只能邮购一个Selector。但是现在,你可以很方便地再定义一个getRSelector()方法,让它返回一个会倒过来访问这个序列的Selector。显然只有内部类才能提供这种灵活性。
3,内部类对象创建的时机与宿主类对象的创建没有什么关系。
4,内部类不存在什么让人头晕的&#8220;是&#8221;关系;他是一个独立的实体
闭包和回调
闭包和回调
&1//:&c08:Callbacks.java
&2//&Using&inner&classes&for&callbacks
&3import&com.bruceeckel.simpletest.*;
&5interface&Incrementable&{
&6&&void&increment();
&9//&Very&simple&to&just&implement&the&interface:
<span style="color: #class&Callee1&implements&Incrementable&{
<span style="color: #&&private&int&i&=&<span style="color: #;
<span style="color: #&&public&void&increment()&{
<span style="color: #&&&&i++;
<span style="color: #&&&&System.out.println(i);
<span style="color: #&&}
<span style="color: #}
<span style="color: #
<span style="color: #class&MyIncrement&{
<span style="color: #&&void&increment()&{
<span style="color: #&&&&System.out.println("Other&operation");
<span style="color: #&&}
<span style="color: #&&static&void&f(MyIncrement&mi)&{&mi.increment();&}
<span style="color: #}
<span style="color: #
<span style="color: #//&If&your&class&must&implement&increment()&in
<span style="color: #//&some&other&way,&you&must&use&an&inner&class:
<span style="color: #class&Callee2&extends&MyIncrement&{
<span style="color: #&&private&int&i&=&<span style="color: #;
<span style="color: #&&private&void&incr()&{
<span style="color: #&&&&i++;
<span style="color: #&&&&System.out.println(i);
<span style="color: #&&}
<span style="color: #&&private&class&Closure&implements&Incrementable&{
<span style="color: #&&&&public&void&increment()&{&incr();&}
<span style="color: #&&}
<span style="color: #&&Incrementable&getCallbackReference()&{
<span style="color: #&&&&return&new&Closure();
<span style="color: #&&}
<span style="color: #}
<span style="color: #
<span style="color: #class&Caller&{
<span style="color: #&&private&Incrementable&callbackR
<span style="color: #&&Caller(Incrementable&cbh)&{&callbackReference&=&&}
<span style="color: #&&void&go()&{&callbackReference.increment();&}
<span style="color: #}
<span style="color: #
<span style="color: #public&class&Callbacks&{
<span style="color: #&&private&static&Test&monitor&=&new&Test();
<span style="color: #&&public&static&void&main(String[]&args)&{
<span style="color: #&&&&Callee1&c1&=&new&Callee1();
<span style="color: #&&&&Callee2&c2&=&new&Callee2();
<span style="color: #&&&&MyIncrement.f(c2);
<span style="color: #&&&&Caller&caller1&=&new&Caller(c1);
<span style="color: #&&&&Caller&caller2&=&new&Caller(c2.getCallbackReference());
<span style="color: #&&&&caller1.go();
<span style="color: #&&&&caller1.go();
<span style="color: #&&&&caller2.go();
<span style="color: #&&&&caller2.go();
<span style="color: #&&&&monitor.expect(new&String[]&{
<span style="color: #&&&&&&"Other&operation",
<span style="color: #&&&&&&"<span style="color: #",
<span style="color: #&&&&&&"<span style="color: #",
<span style="color: #&&&&&&"<span style="color: #",
<span style="color: #&&&&&&"<span style="color: #"
<span style="color: #&&&&});
<span style="color: #&&}
<span style="color: #}&///:~
<span style="color: #
这段程序还进一步揭示了&#8220;让宿主类去实现接口&#8221;和&#8220;交给内部类去做&#8221;之间的区别
Callee2继承了MyIncrement,而MyIncrement已经包括了一个它自己的increment(),而且这个方法的功能同Incrementable接口所定义的毫无相关。所以Callee2继承MyIncrement之后,就不能靠实现Incrementable接口来覆写increment()了,这就逼着你只能使用内部类来提供一个独立的实现了。
注意一下创建匿名内部类的不一定一定是Interface和abstract class,具体的类也可以,比如new Thread(){run(){}}.start();
阅读排行榜
评论排行榜

我要回帖

更多关于 内部接口参数错误 的文章

 

随机推荐