终于看到内部类了,感觉很乱,什么类的内部可以定义其它的类,函数内也可以定义类。感觉语法还可以理解,但不明白我们为什么需要内部类?
像类的继承,或类中引用其它类,这我能理解我们在工作中确实需要这些技巧,但在看内部类时,除了感觉到规则很麻烦外,没有觉得它的必要性,所以在这里向各位讨教,谁能给我举个例子,我们为什么需要内部类。
谢谢
像类的继承,或类中引用其它类,这我能理解我们在工作中确实需要这些技巧,但在看内部类时,除了感觉到规则很麻烦外,没有觉得它的必要性,所以在这里向各位讨教,谁能给我举个例子,我们为什么需要内部类。
谢谢
a、内部类方法可以访问该类定义所在作用域中的数据,包括私有数据成员。
b、内部类可以对同一包中的其他类隐藏起来;
c、当想要定义一个回调函数而不想写太多代码时,使用内部类比较便捷。内部类是一种编译时概念,与虚拟机无关,编译器会将内部类翻译成用$分隔外部类名与内部类名的常规文件。而编译器将一无所知。
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;/**
* 这个类代表贪吃蛇的活动场所
* @author bjsxt
* @version 1.0
*/
public class Yard extends Frame { PaintThread paintThread = new PaintThread();
private boolean gameOver = false; //游戏是否结束
/**
* 行数
*/
public static final int ROWS = 30;
public static final int COLS = 30;
public static final int BLOCK_SIZE = 15;
private Font fontGameOver = new Font("宋体", Font.BOLD, 50);
private int score = 0;
Snake s = new Snake(this);
Egg e = new Egg();
Image offScreenImage = null;
public void launch() {
this.setLocation(200, 200);
this.setSize(COLS * BLOCK_SIZE, ROWS * BLOCK_SIZE);
this.addWindowListener(new WindowAdapter() { @Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
this.setVisible(true);
this.addKeyListener(new KeyMonitor());
new Thread(paintThread).start();
}
public static void main(String[] args) {
new Yard().launch();
}
public void stop() {
gameOver = true;
}
@Override
public void paint(Graphics g) {
Color c = g.getColor();
g.setColor(Color.GRAY);
g.fillRect(0, 0, COLS * BLOCK_SIZE, ROWS * BLOCK_SIZE);
g.setColor(Color.DARK_GRAY);
//画出横线
for(int i=1; i<ROWS; i++) {
g.drawLine(0, BLOCK_SIZE * i, COLS * BLOCK_SIZE, BLOCK_SIZE * i);
}
for(int i=1; i<COLS; i++) {
g.drawLine(BLOCK_SIZE * i, 0, BLOCK_SIZE * i, BLOCK_SIZE * ROWS);
}
g.setColor(Color.YELLOW);
g.drawString("score:" + score, 10, 60);
if(gameOver) {
g.setFont(fontGameOver);
g.drawString("游戏结束", 120, 180);
paintThread.pause();
}
g.setColor(c);
s.eat(e);
e.draw(g);
s.draw(g);
}
@Override
public void update(Graphics g) {
if(offScreenImage == null) {
offScreenImage = this.createImage(COLS * BLOCK_SIZE, ROWS * BLOCK_SIZE);
}
Graphics gOff = offScreenImage.getGraphics();
paint(gOff);
g.drawImage(offScreenImage, 0, 0, null);
}
private class PaintThread implements Runnable {
private boolean running = true;
private boolean pause = false;
public void run() {
while(running) {
if(pause) continue;
else repaint();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void pause() {
this.pause = true;
}
public void reStart() {
this.pause = false;
s = new Snake(Yard.this);
gameOver = false;
}
public void gameOver() {
running = false;
}
}
private class KeyMonitor extends KeyAdapter { @Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_F2) {
paintThread.reStart();
}
s.keyPressed(e);
}
}
/**
* 拿到所得的分数
* @return 分数
*/
public int getScore() {
return score;
}
/**
* 设置所得的分数
* @param score 分数
*/
public void setScore(int score) {
this.score = score;
}}
这是贪吃蛇的背景类,里面用内部类来实现一个线程
不过总的设计还是应该向2楼说的那样
一般的非内部类,是不允许有 private 与protected权限的,但内部类可以
2.内部类拥有外围类的所有元素的访问权限
3.可是实现多重继承
4.可以避免修改接口而实现同一个类中两种同名方法的调用。另外,还有匿名内部类,在事件监听中常用的
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Label;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
class TFFrame extends Frame{
TextField num1,num2,num3;
public void launchFrame()
{
num1=new TextField(10);
num2=new TextField(10);
num3=new TextField(10);
Label lblPlus=new Label("+");
Button btnEqual=new Button("=");
btnEqual.addActionListener(new MyMonitor());
this.setLayout(new FlowLayout());
this.add(num1);
this.add(lblPlus);
this.add(num2);
this.add(btnEqual);
this.add(num3);
this.pack();
this.setVisible(true);
}
//内部类,(方便的)可以直接访问包装类的成员变量和方法.不准许不需要其他类访问。
private class MyMonitor implements ActionListener
{
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
int n1=Integer.parseInt(num1.getText());
int n2=Integer.parseInt(num2.getText());
num3.setText(""+(n1+n2));
}
}
}public class Test {
public static void main(String[] args) {
new TFFrame().launchFrame();
}
}
以上代码如果不用内部类 import java.awt.Frame;
import java.awt.*;class TFFrame extends Frame{
TextField num1,num2,num3;
public void launchFrame()//把Frame运行以来
{
TextField num1=new TextField(10);
TextField num2=new TextField(10);
TextField num3=new TextField(15);
Label lblPlus=new Label("+");
Button btnEqual=new Button("=");
btnEqual.addActionListener(new MyMonitor(this));
this.setLayout(new FlowLayout());
this.add(num1);
this.add(lblPlus);
this.add(num2);
this.add(btnEqual);
this.add(num3);
this.pack();
this.setVisible(true);
}
public static void main(String[] args) {
new TFFrame().launchFrame();
}
}
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.*;
class MyMonitor implements ActionListener{ TFFrame tff=null;
public MyMonitor(TFFrame tff)
{
this.tff=tff;
}
public void actionPerformed(ActionEvent e) {
int n1=Integer.parseInt(tff.num1.getText());
int n2=Integer.parseInt(tff.num2.getText());
tff.num3.setText(" "+(n1+n2));
}}
可以看出MyMonitor这个类完全是为TFFrame服务的
如果我们想方便访问某个类中的信息,我们可以选择:
1持有对方引用
2内部类
很常见的就说说2方法:
常见的就是做GUI时,我们某个窗体Frame添加监听器时,我们对不同的窗体的监听器是不同的,没有必要共享,只要这个Frame能用就可以了,这时经常将监听器
Listener定义成内部类,结构如下:class WindowFrame extends Frame {
public void launchFrame(){
this.set
this.addWindowListener(new WListener());
} private class WListener implements WindowListener { }
}
比如我们编写Applet小应用程序的时候,需要用到监听器,而有时候我们不需要实现特定接口中所有的方法,只要继承某个实现类,重写其中需要用到的方法即可,这时可以用内部类的方式
例如:
Frame f=new Frame("accp");
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent arg0) {
// TODO Auto-generated method stub
System.exit(0);
}
});