java-内部类有什么作用?

356 阅读3分钟

答:内部类提供在一个类中实现同一接口的多次机会。

要知道,在一般类中是不能实现同一个方法两次的。因为接口的实现可以超过一个,但类仅仅能继承一个。

注释:如果这个类有多个内部类的话,其每个内部类的实例都能作为参数传递给调用该父类的方法。在每个内部类中可以分别实现同一个接口方法。

示例1:以内部类执行动画效果:让圆圈从画面左上方移动到右下方

import javax.swing.*;
import java.awt.*;

public class SimpleAnimation {
    //在主要的GUI中创建两个实例变量用来代表图形的坐标
    int x = 70;
    int y = 70;

    public static void main(String[] args) {
        SimpleAnimation gui = new SimpleAnimation();
        gui.go();
    }

    private void go() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        MyDrawPanel3 drawPanel = new MyDrawPanel3();

        frame.getContentPane().add(drawPanel);
        frame.setSize(300, 300);
        frame.setVisible(true);
      
        //重点:重复130次
        for (int i = 0; i < 130; i++) {
            x++;
            y++;

            drawPanel.repaint();

            try {
                //加上延迟可以放慢,不然一下就会跑完。
                Thread.sleep(50);
            } catch (Exception ex) {
            }
        }
    }//关闭go方法

    class MyDrawPanel3 extends JPanel {
        protected void paintComponent(Graphics g) {
            g.setColor(Color.green);
            g.fillOval(x, y, 40, 40);
        }
    }//关闭内部类
}//关闭外部类

效果1:有BUG

这跟我们想的有点出入,原因是我们忘记了要擦掉原来的图形

class MyDrawPanel3 extends JPanel {
    protected void paintComponent(Graphics g) {
        //01把颜色设定为白色
        g.setColor(Color.white);
        //02然后填满整个方块区域
        g.fillRect(0,0,this.getWidth(),this.getHeight());
        g.setColor(Color.green);
        g.fillOval(x, y, 40, 40);
    }
}

效果2:满足要求

示例2:使用java随机产生的图形来跟着节奏起舞

import javax.sound.midi.*;
import javax.swing.*;
import java.awt.*;

//我们必须先监听ControllerEvent,因此实现了这个接口
public class MusicPlayer {
    static JFrame f=new JFrame("我的第一个音乐视频");
    static MyDrawPanel ml;

    public static void main(String[] args) {
        MusicPlayer musicPlayer=new MusicPlayer();
        musicPlayer.go();
    }//关闭main
    public void setUpGui(){
        ml=new MyDrawPanel();
        f.setContentPane(ml);
        f.setBounds(30,30,300,300);
        f.setVisible(true);
    }//关闭方法
    private void go() {
        setUpGui();
        try {
            //创建并打开队列
            Sequencer sequencer= MidiSystem.getSequencer();
            sequencer.open();
            //向sequencer注册事件。注册的方法取用监听者与代表想要监听的事件的int数组,我们只需要127事件
            sequencer.addControllerEventListener(ml,new int[]{127});
            //创建队列并trace
            Sequence seq=new Sequence(Sequence.PPQ,4);
            Track track=seq.createTrack();
            //创建一堆连续的音符事件
            int r=0;
            for (int i = 5; i <60 ; i+=4) {
                r=(int)((Math.random()*50)+1);
                //调用makeEvent()来产生信息和事件,然后把它们加到track上
                track.add(makeEvent(144,1,r,100,i));
                //插入事件编号为127的自定义controllerEvent(176),它不会做任何事情,只是让我们知道有音符
                //被播放,因为它的tick跟NOTE ON是同时进行的
                track.add(makeEvent(176,1,127,0,i));
                track.add(makeEvent(128,1,r,100,i+2));
            }//结束循环
            sequencer.setSequence(seq);
            sequencer.setTempoInBPM(120);
            sequencer.start();
        }catch (Exception ex){ex.printStackTrace();}//结束循环
    }//关闭

    private static MidiEvent makeEvent(int comd, int chan, int one, int two, int tick) {
      MidiEvent event=null;
      try {
          ShortMessage a=new ShortMessage();
          a.setMessage(comd,chan,one,two);
          event=new MidiEvent(a,tick);
      }catch (Exception e){
          return event;
      }
      return event;
    }//关闭方法

    class MyDrawPanel extends JPanel implements ControllerEventListener{
        //获知事件时才会为真
        boolean msg=false;
        //获知事件时设为真并调用重绘程序
        public void controlChange(ShortMessage event){
            msg=true;
            repaint();
        }
        public void paintComponent(Graphics g) {
            //因为也有其他东西会引发重绘,所以要判断是否为controllerEvent所引发的
            if (msg){
                Graphics2D g2=(Graphics2D)g;
                //产生随机的颜色并画出方块
                int r=(int)(Math.random()*250);
                int gr=(int)(Math.random()*250);
                int b=(int)(Math.random()*250);

                g.setColor(new Color(r,gr,b));

                int ht=(int)((Math.random()*120)+10);
                int width=(int)((Math.random()*120)+10);
                int x=(int)((Math.random()*40)+10);
                int y=(int)((Math.random()*40)+10);

                g.fillRect(x,y,width,ht);
                msg=false;
            }//if结束
        }//关闭方法
    }//关闭内部类
}//关闭类

效果2: