1、成员内部类
特点:
一、可以使用外部类的任何成员,包括private私有的。
直接使用或者OuterClass.this.xxxxx
二、修饰符更丰富
private 外部类私有,其他地方不可使用。
public 公开。使用方式:OuterClass.InnerClass
default(不写)
注意:普通类只有public 和 默认(不写任何修饰符)包2种访问权限。
public class demo
{
public static void main(String[] args)
{
JFrame win = new JFrame("测试");
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
win.getContentPane().add(new MainPanel());
win.pack();
win.setVisible(true);
}
}
class MainPanel extends JPanel
{
private JButton buttonAdd,buttonCut;
private JLabel label1;
public MainPanel()
{
super();
this.setPreferredSize(new Dimension(520,300));
this.setBackground(Color.WHITE);
label1 = new JLabel("no dog",SwingConstants.CENTER);
buttonAdd = new JButton("Add dog");
buttonAdd.addActionListener(new ButtonListener());
buttonAdd.setCursor(new Cursor(Cursor.HAND_CURSOR));
buttonCut = new JButton("Cut dog");
buttonCut.addActionListener(new ButtonListener());
buttonCut.setCursor(new Cursor(Cursor.HAND_CURSOR));
this.add(label1);
this.add(buttonAdd);
this.add(buttonCut);
}
private class ButtonListener implements ActionListener
{
/*内部类ButtonListener可以直接使用外部类MainPanel的字段 */
@Override //事件监听对象的事件处理方法
public void actionPerformed(ActionEvent eventObj) {
String preText = label1.getText();
if(eventObj.getSource() ==buttonAdd )
{
if(preText.equals("no dog"))
{
label1.setText("1 dog");
}
else
{
String[] seps = preText.split(" ",2);
int preSum = Integer.parseInt(seps[0]);
label1.setText(Integer.toString(++preSum)+" dogs");
}
}
else if(eventObj.getSource() ==buttonCut)
{
String[] seps = label1.getText().split(" ",2);
int preSum;
try{
preSum = Integer.parseInt(seps[0]); //解析"no" 会出现异常
if(preSum == 1)
{
label1.setText("no dog");
}
else
{
label1.setText(Integer.toString(--preSum)+" dogs");
}
}catch(NumberFormatException e)
{
Toolkit.getDefaultToolkit().beep(); //警铃
JOptionPane.showMessageDialog(null, "已经没有dog了!!!"); //弹出消息框
}
}
}
}
}
由于java的事件处理程序依靠的是类对象(这个对象必须要实现接口),而不是像C#那样的单独的方法,所以,我们需要定义一个类专门处理事件。但是一个独立的类之间数据访问会很复杂。这个时候内部类就是最佳解决方法了。
那么,内部类为什么可以直接使用外部类的成员呢?据core java的理解,内部类会自动增加一个字段,这个字段正是外部类当前对象的引用。而且内部类在的构造函数中会自动用外部内当前对象去初始化这个引用。当然,这个过程是隐式完成的。简单的说:在内部类中有一个引用,他指向当前外部类的对象。所以内部类中的所有影响外部类的操作,都会反应到外部类对象上。
2、静态内部类
静态内部类没有外部类的引用,因此,他不能使用外部类的对象。静态内部类一般用来单向的为外部类提供服务。静态类也可以隐藏在内部类之中,private修饰。
静态类用static修饰。但不代表他不能实例化(心里还有C#的阴影o(︶︿︶)o )
public class MianClass
{
public static void main(String[] args)
{
int[] arr = new int[10];
for(int i=0;i<arr.length;i++)
arr[i] = (int)(Math.random()*10);
System.out.println(Find.findMax(arr));
System.out.println(Find.findMin(arr));
}
private static class Find
{
public static Integer findMax(int[] arr)
{
if(arr == null || arr.length==0) return null;
int max = arr[0];
for(int i=1;i<arr.length;i++)
if(arr[i]>max)
max = arr[i];
return max;
}
public static Integer findMin(int[] arr)
{
if(arr == null || arr.length==0) return null;
int min = arr[0];
for(int i=1;i<arr.length;i++)
if(arr[i]<min)
min = arr[i];
return min;
}
}
}
3、方法内部类
在一个方法的内部定义的类,这个类仅仅能被这个方法使用。而这个类可以使用外部类的任何成员,以及它所在
方法的fina变量。不能有访问修饰符,因为只能在方法中使用,修饰符无意义。
一、定义时无访问修饰符
二、类可以使用外部类的成员和本它所在方法的final变量。
4、匿名内部类
一个类只使用一次,不需要定义他的引用来保存对象的地址。
由于匿名类没有名字,所以没有构造函数。创建时只能通过他的接口或者父类来new,参数则传给他的父类的构造函数。
new Interface(){.....}
new SuperClass(){.....}
//为一个button添加事件处理程序
buttonClear.addActionListener(new ListenerClear(){
@Override
public void actionPerformed(ActionEvent arg0) {
expressionArea.setText("");
}
});