Topic: anonymouse inner class的问题

  Print this page

1.anonymouse inner class的问题 Copy to clipboard
Posted by: daywalker
Posted on: 2003-04-17 17:40

在thinking in java(2nd Edition 中文)中有这样一段话:
"如果anonymous inner class用到定义于inner class之外的某个对象/变量, 则编译器会限制该对象/变量为final"(第267页)
旁边的例子也印证了这段话
但是现在又有一段代码
import javax.swing.*;
import java.awt.*;

public class NotHelloWorld{
  public static void main(String[] args){
    NotHelloWorldFrame frame = new NotHelloWorldFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.show();
  }
}

/**
A frame that contains a message panel
*/
class NotHelloWorldFrame extends JFrame{
/////////////////
  String message="Hello,World";;
/////////////////

  public NotHelloWorldFrame(){
    setTitle("NotHelloWorld");
    setSize(WIDTH,HEIGHT);

    // add panel to frame
    NotHelloWorldPanel panel=new NotHelloWorldPanel();
    Container contentPane=getContentPane();

    contentPane.add(new JPanel(){
      public void paintComponent(Graphics g){
        Graphics2D g2=(Graphics2D)g;

        super.paintComponent(g2);

        g2.setFont(new Font("SansSerif",Font.BOLD+Font.ITALIC,14));
///////////////////////////////////////////////////////////////////////////////////
        g2.drawString(message,75,100);
//////////////////////////////////////////////////////////////////////////////////
      }
    });

  }

  public static final int WIDTH=300;
  public static final int HEIGHT=200;
}

请注意注释中的语句
在anonymouse inner class中使用的message定义于inner class之外, 但并非final,显然这段代码没有问题.
有哪位老大可以给我解释一下这段话的含义是什么,也就是说在什么情况下开始那一段话才成立?谢谢

2.Re:anonymouse inner class的问题 [Re: daywalker] Copy to clipboard
Posted by: Jove
Posted on: 2003-04-17 17:44

message是类的属性,在inner class中是可以访问的
你一开始引用的那句话不全面,或是表达的有问题

3.Re:anonymouse inner class的问题 [Re: daywalker] Copy to clipboard
Posted by: jiangns3000
Posted on: 2003-04-17 21:55

"如果anonymous inner class用到定义于inner class之外的某个对象/变量, 则编译器会限制该对象/变量为final"(第267页)
如果不考虑上下文理解的话,我认为这句话不对。
其实匿名inner class 与不匿名inner class 本质上是一样,(如上述匿名 inner class编译后,JAVAC照样给它取一个名字生成一个class: NotHelloWorldFrame$1.class)所有inner class(无论是否匿名,都能访问它作用域中的局部变量或类中变量或方法),这样给事件处理带来方便。

4.Re:anonymouse inner class的问题 [Re: daywalker] Copy to clipboard
Posted by: floater
Posted on: 2003-04-18 00:30

Yes, it's correct, otherwise you will get a compiler error. But it seems unnatural to me, I couldn't figure out why they have such a rule.

In your code, try to move message definition to the line right above where you do your "new Panel() { ...".

5.Re:anonymouse inner class的问题 [Re: daywalker] Copy to clipboard
Posted by: jiangns3000
Posted on: 2003-04-18 16:59

我不明白。我认为那句话有问题。
见下例:
class Outer {
int i = 100;
void classMethod() {
final int l = 200;
Runnable r=new Runnable(){
public void run(){
int k = i; // compile-time error???此处有编译错吗?我认为没有.i(Outer之中)不是final,这不是与那句话矛盾吗?(匿名类中访问外部非final)
int m = l; // ok
}
};
}

void foo() {
class Local { // a local class
int j = i;//此处OK,非匿名类访问.
}
}
}

6.Re:anonymouse inner class的问题 [Re: daywalker] Copy to clipboard
Posted by: film2000
Posted on: 2003-04-18 18:43

anonymous inner class可以访问外部类的类变量,但不能访问外部函数的一般变量,除非该变量为final类型.
public class Test
{
  String classString = "classString";
  
  public void testOne()
  {
    String methodString = "methodString";
    final String methodStringFinal = "methodStringFinal";
    System.out.println(
      new Object()
      {
        public String toString()
        {
          String s = classString;///OK!
          s += methodStringFinal; ///OK!
          s += methodString;//ERROR
          return s;
        }
      }
    Wink;
  }
}

原因如下:当testOne方法退出时,methodString可以被当作垃圾回收掉,因而methodString的生命期结束,但是anonymouse inner class不会因为testOne方法退出而消亡,所以必须把外部临时变量定义为final类型,这样临时变量就不会放在stack,而放在专门的内存里.

我讲的不是很清楚,不知各位能否看懂!》

7.Re:anonymouse inner class的问题 [Re: daywalker] Copy to clipboard
Posted by: jiangns3000
Posted on: 2003-04-18 20:54

不。我认为“生命期”的解释不对。假如这个解释成立,会推出:anonymouse inner class 不能访问外部类的类变量 这一个矛盾。
如下例:(以下代码例子想说明:匿名类对象空间没有被回收,而外部类对象空间却被回收。故会推出:anonymouse inner class 不能访问外部类的类变量 这一个矛盾。所以我认为“生命期”的解释不对。)

class Test
{
String classString = "classString";
Testb tb;
public Test(Testb tb){this.tb=tb;}
public void testOne()
{
String methodString = "methodString";
final String methodStringFinal = "methodStringFinal";
Object op= new Object()
{
public String toString()
{
String s = classString;///OK!
s += methodStringFinal; ///OK!
// s += methodString;//ERROR
return s;
}
};
;
tb.give(op);
}
}

class Testb
{ Object obj;
public void give(Object ob){obj=ob;}
}
public class Application1{
//在main()方法中
public static void main(String[] args) {
Testb mtb=new Testb();
new Test(mtb).testOne() ;//将anonymouse inner class 对象引用传给mtb
//此时外部类Test的对象空间将被回收,而anonymouse inner class 对象不能回收.
//故匿名类不能访问外部类的类变量.岂不奇怪?
//mtb 做其它事情.没有人再使用外部类对象
}
}


8.Re:anonymouse inner class的问题 [Re: daywalker] Copy to clipboard
Posted by: floater
Posted on: 2003-04-19 06:04

Thinking in Java:
Chapter 8, section "The link to the outer class"
So far, it appears that inner classes are just a name-hiding and code-organization scheme, which is helpful but not totally compelling. However, there’s another twist. When you create an inner class, an object of that inner class has a link to the enclosing object that made it, and so it can access the members of that enclosing object—without any special qualifications. In addition, inner classes have access rights to all the elements in the enclosing class

9.Re:anonymouse inner class的问题 [Re: daywalker] Copy to clipboard
Posted by: jiangns3000
Posted on: 2003-04-19 12:34

明白了。这个结一下子解开了。多谢!


   Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent
Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1
客服电话 18559299278    客服信箱 714923@qq.com    客服QQ 714923