A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 何家旺 黑马粉丝团   /  2013-1-24 19:48  /  1480 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 以计盛 于 2013-1-25 16:30 编辑

java匿名类到底怎么用,怎么就不会用呢!能不能来点代码解释解释一下!

8 个回复

倒序浏览
必须要继承一个父类或接口,才可以使用匿名内部类
比如
  1.         new Runnable(){ //继承一个接口

  2.                         @Override
  3.                         public void run() { //实现接口内的方法
  4.                                 // TODO Auto-generated method stub
  5.                                
  6.                         }
  7.                        
  8.                 }
复制代码
回复 使用道具 举报
局部匿名内部类:又叫匿名类!  匿名类不能有构造器
1 匿名内部类的语法
  把一个类的定义放到new语句中去了。
  一个东西没名字,就表示它只能被使用一次!
  一个类要是没有名字,那么这个类只能被使用一次!
  问一下自己:定义一个类什么目的?为了创建这个类的对象!
  也就是说,因为一个匿名类只能被使用一次,那么我们就需要在这时创建它的对象!
  
  所以匿名内部类必须放到new语句中使用。
  
  new 接口或父类名() {类体}
  
  new A();  new A() {};
  new A():创建A类的对象。
  A a = new A() {}:创建A类的子类对象,而这个子类也是刚刚创建的。这个子类没有名字!虽然不知道这个子类叫什么名字,但可以使用A类的引用来指向它!
  也就是说,我们只能使用他父类的引用来指向它,那么这个引用也就只能调用A类中存在的方法,而不能再去调用子类独有的方法。
  这说明,匿名内部中,都是在重写父类方法,如果写独有方法,也没能被调用,那么你写它干什么。


2 匿名内部类只能使用一次
  只能被使用一次,对类的使用也就一种方式,创建这个类的对象!

3 匿名内部类必须指定父类或者指定实现的接口
  new 父类或接口(){}
  必须指定父类或者实现的接口。
  匿名内部类与正常类不一样,它只能指定一个要继承的类或者是指定一个要实现的接口。两者不能兼得!
  实现接口,也只能实现1个。要实现接口,就不能指定父类!

4 匿名内部类不能同时继承和实现
  匿名内部类与正常类不一样,它只能指定一个要继承的类或者是指定一个要实现的接口。两者不能兼得!
  实现接口,也只能实现1个。要实现接口,就不能指定父类!

5 匿名内部类最多实现一个接口
  实现接口,也只能实现1个。要实现接口,就不能指定父类!
回复 使用道具 举报
public class FrameDemo {
        FrameDemo(){
                init();
        }
        //定义图形中所需组件的引用
        private Frame f;
        private Button but;
       
        public void init(){
               
        f=new Frame("my Frame");
        //对Frame窗体进行基本设置
        f.setBounds(200,100,600,400);
        but =new Button("my Button");
        f.setLayout(new FlowLayout());
        //Button添加到Frame
        f.add(but);       
        f.setVisible(true);
       
        myEvent();
        }
        public void myEvent(){
                //窗体监听事件
                f.addWindowListener(new WindowAdapter(){
                        public void windowClosing(WindowEvent e){
                                System.exit(0);
                        }
                });
                //按钮监听事件
                but.addActionListener(new  ActionListener(){
                        public void actionPerformed(ActionEvent e){
                                //System.exit(0);
                                System.out.println("button OK");
                        }       
                });
                //在按钮上添加鼠标事件
       
                but.addMouseListener(new  MouseAdapter(){
                        int count=1;
                        int click=1;
                        public void mouseEntered(MouseEvent e){
                                System.out.println("鼠标进入到该组件"+count++);
                        }       
                        public void mouseClicked(MouseEvent e){
                                if(e.getClickCount()==2)
                                System.out.println("双击动作"+click++);
                        }       
                });
        }
        //让按钮具备退出功能,按钮就是事件源
        //通过查阅Button描述,发现按钮支持一个特有监听:addActionListener
       
        public static void main(String[] args) {
               
new FrameDemo();
        }
}
如在这个例子中,在gui的学习中,为鼠标键盘等添加监听事件,就是用的new接口的实现类,即匿名内部类的格式来操作的。很方便。既然学了肯定会有用
回复 使用道具 举报
本帖最后由 刘郑瑞 于 2013-1-24 21:05 编辑

详细请看我的博客:http://liuzr1026.blog.163.com   
匿名内部类就是在一个类或方法中创建一个没有引用的新对象。new Shape(){}  常用的是 new 接口  {实现方法体。。。。。}
public Shape getShape() {  
return new Shape() {     //new Shape()是内部类,后面紧跟着方法体。  
public void paint() {
   System.out.println("painter paint() method");   
}

interface Shape {
public void paint();
}
回复 使用道具 举报
public class Parcel6 {
  public Contents cont() {
    return new Contents() {
      private int i = 11;
      public int value() { return i; }
    }; // Semicolon required in this case
  }
  public static void main(String[] args) {
    Parcel6 p = new Parcel6();
    Contents c = p.cont();
  }
} ///:~

cont()方法同时合并了返回值的创建代码,以及用于表示那个返回值的类。除此以外,这个类是匿名的——它没有名字。
return new Contents()返回一个没有名称的内部类(匿名内部类)
回复 使用道具 举报
本帖最后由 黑马张旭 于 2013-1-25 09:20 编辑

这个例子我绝得不错  可以参考下

  因为匿名内部类没有名字这个特殊性质,所以我们无从给它指定构造方法,构造方法必须和类名同名,类名都没有,构造方法就无从谈起了。但是匿名内部类可以通过直接调用父类的构造方法实现初始化,当然要求父类构造方法对它父类中定义的成员变量进行初始化。这里用一个例子看创建匿名内部类的时候父类的构造方法到底是如何调用的。


public class Main {

    public static void main(String[] args) {
        InnerTest inner = new InnerTest();
        Test t = inner.get(3);
        System.out.println(t.getI());
    }
}

class Test {  //超类
    private int i;
    public Test(int i) {
        this.i = i;
    }
    public int getI() {
        return i;
    }
}

class InnerTest {  //用于内部类的测试
    public Test get(int x) {
        return new Test(x) {  //创建匿名内部类,调用父类的构造方法
            @Override
            public int getI() {
                return super.getI() * 10;
            }
        };
    }
}


编译得到4个class文件,这里只需要关注InnerTest.class 和 InnerTest$1.class。这里InnerTest$1.class是匿名内部类的class文件,InnerTest.class是InnerTest类的class文件。我们先看InnerTest$1.class的内容:
javap -c InnerTest$1 > InnerTest$1.txt
得到代码如下 :



Compiled from "Main.java"
class InnerTest$1 extends Test{
final InnerTest this$0;

InnerTest$1(InnerTest, int);
  Code:
   0:    aload_0
   1:    aload_1
   2:    putfield    #1; //Field this$0:LInnerTest;
   5:    aload_0
   6:    iload_2
   7:    invokespecial    #2; //Method Test."<init>":(I)V
   10:    return

public int getI();
  Code:
   0:    aload_0
   1:    invokespecial    #3; //Method Test.getI:()I
   4:    bipush    10
   6:    imul
   7:    ireturn

}


很明显,我们的匿名内部类有了名字 InnerTest$1 ,而且是继承自 Test
class InnerTest$1 extends Test
这个类中有一个成员final InnerTest this$0;我想这应该是该内部类所在的外部类InnerTest的引用
这个匿名内部类的构造方法是:
InnerTest$1(InnerTest, int);
一个是InnerTest类型,也就是该类外部类的引用,调用的时候应该是把外部类对象的this指针传给它,这样就内部类就可以直接访问外部类的成员了。
另一个就是int类型的,应该是对i进行初始化用的。
看到下面这行:
7:        invokespecial        #2; //Method Test."<init>":(I)V
现在应该清楚了,这是调用了父类Test的构造方法。
下面再看InnerTest是如何实现的:
Java code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Compiled from "Main.java"
class InnerTest extends java.lang.Object{
InnerTest();
  Code:
   0:    aload_0
   1:    invokespecial    #1; //Method java/lang/Object."<init>":()V
   4:    return

public Test get(int);
  Code:
   0:    new    #2; //class InnerTest$1
   3:    dup
   4:    aload_0
   5:    iload_1
   6:    invokespecial    #3; //Method InnerTest$1."<init>":(LInnerTest;I)V
   9:    areturn

}




InnerTest的get方法是关键。
这里首先new InnerTest$1,后面调用了InnerTest$1的构造方法,并把两个参数传了进去。
这样一切都清楚了。
结论:其实匿名内部类也没有什么特别的地方,编译之后它有了名字,有了构造方法,就是一个正常的类了。
有理解不对的地方,请大家指正



回复 使用道具 举报
O(∩_∩)O谢谢  大侠们
回复 使用道具 举报
高浩 中级黑马 2013-1-25 13:23:45
9#
匿名内部类就是为了简化书写,而成立的
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马