head first java( 第12章 )

- 检测事件方法和执行的方法

  检测事件方法: 比如如何知道鼠标被按下 ?

  执行事件方法: 知道了鼠标被按下以后, 应该执行什么.

- 监听接口

  事件源: 指类似button 这种, 会在用户作出相关动作时(按下按钮)产生事件对象. ( 这部分一般不用我们管 )

  事件源必指定监听接口, 例如 button.addActionListener(this) // this 是 actionListener的引用

  监听接口: 是介于监听(你)与事件源(按钮)之间的桥梁

  每个事件类型都有相对应的监听接口. 某些接口不止有一个方法, 例如 MouseListener, 有单击, 双击 等等

- 如何判断是否为事件源

  如果该对象有类似 addMouseListener 等方法的话,那么它就是事件源, 查API 

- 事件触发必须的做的两件事 

  必须事件源部分添加监听该事件的对象, 例如: button.addActionListener(this), 只有这样, 当该事件发生时才知道触发谁(this)

  执行对象部分, 必须有该事件的执行方法, 接口实现.

- 一般流程

  比如, 你想在一个窗体中包含两个button, 分别点击这两个button时, 分别显示"click 1", "click 2". 那么:

  1. 首先创建一个启动类, 这个类中包含 public static void main 方法, 一般包含 public static void main 方法的类, 就只做启动目的, 不做其他内容, 称为测试总类

  2. 创建一个 MyWindow 类, 包含了两个实例变量 button1, button2, 这是两个事件源, 实现方法使用内部类中的 DoClick1, DoClick2 分别实现了不同的button的click,

      这样, 如果你又增加了一个 button, 只需要增加一个实例变量 button3, 并再创建一个内部类来执行点击 button3 时触发的动作, 而对前面的 button1,button2 等相关内容,

      无需任何修改.

TotalTest:

public class TotalTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        MyWindow myWindow = new MyWindow();
        myWindow.go();
    }

}

MyWindow类:

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

class MyWindow  {
    JButton button1;
    JButton button2;
    
    /**
     * @param args
     */
    
    public void go() {
        JFrame frame = new JFrame();
        frame.setLayout(new GridLayout(2, 1));
        button1 = new JButton("click me");
        button2 = new JButton("click me 2");
        
        button1.addActionListener(new DoClick1());
        button2.addActionListener(new DoClick2());
        
        frame.getContentPane().add(button1);
        frame.getContentPane().add(button2);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300, 300);
        frame.setVisible(true);
        
    }
    
    private final class DoClick1 implements ActionListener {
        public void actionPerformed(ActionEvent event) {
            // here need button1 (instance variable )
            button1.setText("1 has already clicked");
        }
    }
    
    private final class DoClick2 implements ActionListener {
        public void actionPerformed(ActionEvent event) {
            // here need button2 (instance variable )
            button2.setText("2 has already clicked");
        }
    }

}

注意: 有几点蹩脚的地方 :
1. 如果click 的实现方法需要访问MyWindow的实例变量 button1, button2, 如果这两个实例变量定位为 private 的, 那么外部无法访问, 只能在这个 MyWindow类内部来实现click方法

2. 在内部实现click方法, 如果是 MyWindow这个类自己本身实现, 那么由于有多个button, 实现的时候就需要判断是哪个button, 这样在增加新的button时软件维护困难(是面向过程的办法), 所以这个时候需要使用内部类, 每个内部类分别实现了不同button的click方法, 当新增加别的button时, 也不需要修改之前的代码, 只需要新增一个实例变量和一个新的内部类就可以了.

内部类的另外用途时, 可以实现多继承.

- 有两个按钮时( 内部类得作用1 )

  我们要实现按钮的监听接口, 怎么办?

  1. 一个对象实现, 因为如果是同一个对象实现的话, 就会出现如下代码:

  image

  这样虽然可以, 但是这看起来不太像面向对象, 如果再增加一个按钮呢 ?

  2. 两个对象实现, 如果是两个对象, 那么就要重新定义类, 而新的类是没有办法识别 button 等实例变量的

  image

  如上: 虽然定义了两个接口实现执行方法, 但是都没有办法调用 frame这个实例的方法? 如果你把所有的变量都定义成 public 的,

  又违背了封装的特性,

  答案: 如果有两个不同的监听类, 他们能够存取 GUI 的实例变量, 并且两者好像互相属于对方一样, 就挺好, 内部类, 是我们的救星

  内部类可以使用外部所有的方法与变量, 就算是私有的也一样, 内部类把存取外部类的方法和变量当作是开自家冰箱.

  如果你从外部类程序代码中初始化内部的类, 此内部对象会绑定在该外部对象上

  imageimage

  现在可以搞定 有两个按钮了:

  image

  image

- 内部类的作用 ( 主要有2个作用)

  1. 提供在一个类中实现同一接口的多次机会. 还有, 任何时候你需要一个独立却又好像另一个类成员之一的类时, 内部类可能是唯一的解.

  2. 内部类被用来当做某种外部类无法继承的子类( 即内部类可以实现多重继承 )

  例如:

类一

package insidecategory;

public class Example1 {

public String name()

{

  return "liutao";

}

}

类二

package insidecategory;

public class Example2 {

public int age()

{

  return 25;

}

}

类三

package insidecategory;

public class MainExample

{

  private class test1 extends Example1 // 继承了 Example1

{

public String name()

{

return super.name();

}

}

private class test2 extends Example2 // 继承了 Example2

{

  public int age()

{

  return super.age();

}

}

public String name()

{

return new test1().name();

}

public int age()

{

return new test2().age();

}

public static void main(String args[])

{

MainExample mi=new MainExample();

System.out.println("姓名:"+mi.name());

System.out.println("年龄:"+mi.age());

}

}

image

image

这个例子, 个人感觉不使用内部类也可以实现.

原文地址:https://www.cnblogs.com/moveofgod/p/3023706.html