1.内部类
1.1 成员内部类:了解
- 类中套类,外面的称为外部类,里面的称为内部类
- 内部类通常只服务于外部类,对外不具备可见性
- 内部类对象需要在外部类中创建
- 内部类中可以直接访问外部类的成员(包括私有的),
内部类中有个隐式的引用指向了创建它的外部类对象:外部类名.this-----API用
public class InnerClassDemo {
public static void main(String[] args) {
Mama m = new Mama();
//Baby b = new Baby(); //编译错误,内部类对外不具备可见性
}
}
class Mama { //外部类
private String name;
void create(){
Baby b = new Baby(); //正确,内部类对象通常在外部类中创建
}
class Baby{ //内部类
void showName(){
System.out.println(name);
//Mama.this指代当前对象的外部类对象
System.out.println(Mama.this.name);
//System.out.println(this.name); //编译错误,this指代当前Baby对象
}
}
}
1.2. 匿名内部类:-------大大简化代码
- 何时用:若想创建一个类(派生类)的对象,并且对象只创建一次,可以设计为匿名内部类
- 匿名内部类中不能修改外面局部变量的值,因为该变量在此处会默认为final的-----API用
- 小面试题:内部类有独立的.class吗? 答:有
public class NstInnerClassDemo {
public static void main(String[] args) {
//1)创建了Aoo的一个派生类,但是没有名字
//2)为该派生类创建了一个对象,名为o1
// ---new Aoo(){}是在创建派生类对象,而后向上造型为Aoo类型
//3)大括号中的为派生类的类体
Aoo o1 = new Aoo(){
};
//1)创建了Aoo的一个派生类,但是没有名字
//2)为该派生类创建了一个对象,名为o2
//3)大括号中的为派生类的类体
Aoo o2 = new Aoo(){
};
int num = 5;
num = 55; //正确
//1)创建了Boo的一个派生类,但是没有名字
//2)为该派生类创建了一个对象,名为o3
//3)大括号中的为派生类的类体
Boo o3 = new Boo(){
void show(){
System.out.println("showshow");
//num = 88; //编译错误,在此处num会默认为final的
}
};
o3.show();
}
}
abstract class Boo{
abstract void show();
}
abstract class Aoo{
}
2.潜艇游戏第七天:
2.1. 潜艇入场:
- 潜艇对象是由窗口产生的,所以在World中设计nextSubmarine()生成潜艇对象
- 潜艇入场为定时发生的,所以在run中调用submarineEnterAction()实现潜艇入场
在submarineEnterAction()中:
每400毫秒,获取潜艇对象obj,submarines扩容,将obj添加到submarines末尾
> 注意: run()中调用submarineEnterAction()之后必须调用repaint()来重画
2.2. 水雷入场:
- 水雷对象是由水雷潜艇发射出来的,所以在MineSubmarine中设计shootMine()生成水雷对象
- 水雷入场为定时发生的,所以在run中调用mineEnterAction()实现水雷入场
在mineEnterAction()中:
每1000毫秒,......---------暂时搁置
2.3. 海洋对象移动:
- 海洋对象移动为对象所共有的行为,所以在SeaObject中设计抽象方法move()实现移动,在6个派生类中重写
- 海洋对象移动为定时发生的,所以在run中调用moveAction()实现海洋对象移动
在moveAction()中:
遍历所有潜艇-潜艇动,遍历所有水雷-水雷动,遍历所有炸弹-炸弹动
2.4代码展示
2.4.1Battleship类
package cn.tedu.submarine;
import javax.swing.*;
import java.util.Objects;
/**
* 战舰
*/
public class Battleship extends SeaObject{
/**
* 命
*/
private int life;
public Battleship() {
super(66,26,270,124,5);
this.life = 5;
}
@Override
public void move() {
}
@Override
public ImageIcon getImage() {
return Images.battleship;
}
/**
* 发射炸弹的方法
*/
public void shootBomb(){
}
}
2.4.2Bomb类
package cn.tedu.submarine;
import javax.swing.*;
import java.util.Objects;
/**
* 炸弹
*/
public class Bomb extends SeaObject{
public Bomb(int x , int y) {
super(9,12,x,y,3);
}
/**
* 炸弹移动的方法
*/
@Override
public void move() {
y += speed;
}
@Override
public ImageIcon getImage() {
return Images.bomb;
}
}
2.4.3Images类
package cn.tedu.submarine;
import javax.swing.ImageIcon;
public class Images {
/**
* 背景图
*/
public static ImageIcon sea;
/**
* 战舰图
*/
public static ImageIcon battleship;
/**
* 炸弹图片
*/
public static ImageIcon bomb;
/**
* 游戏结束
*/
public static ImageIcon gameover;
/**
* 水雷图片
*/
public static ImageIcon mine;
/**
* 水雷潜艇
*/
public static ImageIcon minesubm;
/**
* 侦察潜艇
*/
public static ImageIcon obsersubm;
/**
* 鱼类潜艇
*/
public static ImageIcon torpesubm;
/**
* 初始化图片
*/
static {
battleship = new ImageIcon("img/battleship.png");
sea = new ImageIcon("img/sea.png");
bomb = new ImageIcon("img/bomb.png");
gameover = new ImageIcon("img/gameover.png");
mine = new ImageIcon("img/mine.png");
minesubm = new ImageIcon("img/minesubm.png");
obsersubm = new ImageIcon("img/obsersubm.png");
torpesubm = new ImageIcon("img/torpesubm.png");
}
// /**
// * 测试图片
// * @param args
// */
// public static void main(String[] args) {
// //返回8表示成功了
// System.out.println(battleship.getImageLoadStatus());
// }
}
2.4.4Mine类
package cn.tedu.submarine;
import javax.swing.*;
import java.util.Objects;
/**
* 水雷
*/
public class Mine extends SeaObject{
public Mine(int x , int y) {
super(11,11,x,y,1);
}
/**
* 水雷移动的方法
*/
@Override
public void move() {
y-=speed;
}
@Override
public ImageIcon getImage() {
return Images.mine;
}
}
2.4.5MineSubMarine类
package cn.tedu.submarine;
import javax.swing.*;
import java.util.Objects;
import java.util.Random;
/**
* 水雷潜艇
*/
public class MineSubmarine extends SeaObject{
public MineSubmarine() {
super(63,19);
}
/**
* 水雷潜艇移动
*/
@Override
public void move() {
x+=speed;
}
@Override
public ImageIcon getImage() {
return Images.minesubm;
}
/**
* 发射水雷---生成水雷对象
* @return
*/
public Mine shootMine(){
return new Mine(this.x+this.width,this.y-11);
}
}
2.4.6ObserverSubMarine类
package cn.tedu.submarine;
import javax.swing.*;
import java.util.Objects;
import java.util.Random;
/**
* 侦察潜艇
*/
public class ObserverSubmarine extends SeaObject{
public ObserverSubmarine() {
super(63,19);
}
/**
* 侦察潜艇移动
*/
@Override
public void move() {
x+=speed;
}
@Override
public ImageIcon getImage() {
return Images.obsersubm;
}
}
2.4.7SeaObject类
package cn.tedu.submarine;
import javax.swing.*;
import java.awt.*;
import java.util.Random;
/**
* 海洋对象
*/
public abstract class SeaObject {
public static final int LIVE = 0;//或者的
public static final int DEAL = 1;//死了的
protected int state = LIVE;//当前状态(默认是活着的)
/**
* 成员变量一般都要private的
* 此处设计为protected
* 因为还没有讲到getter/setter
*/
/**
* 宽
*/
protected int width;
/**
* 高
*/
protected int height;
/**
* x轴
*/
protected int x;
/**
* y轴
*/
protected int y;
/**
* 速度
*/
protected int speed;
public SeaObject(int width,int height,int x , int y,int speed){
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.speed = speed;
}
public SeaObject(int width,int height){
this.width = width;
this.height = height;
Random rand = new Random();
x = -width;
y = rand.nextInt(World.HEIGHT-height-150+1 ) +150;
this.speed = rand.nextInt(3)+1;
}
/**
* 移动的方法
*/
public abstract void move();
/**
* 获取对象的图片
*/
public abstract ImageIcon getImage();
/**
* 判断是活着的
* @return
*/
public boolean isLive(){
return state == LIVE;
}
/**
* 判断是死的吗
* @return
*/
public boolean isDeal(){
return state == DEAL;
}
/**
* 画图片
* @param g
*/
public void paintImage(Graphics g){
if (isLive()){//若或者的
//不要求掌握
this.getImage().paintIcon(null,g,this.x,this.y);
}
}
}
2.4.8TorpedoSubmarine类
package cn.tedu.submarine;
import javax.swing.*;
import java.util.Objects;
import java.util.Random;
/**
* 鱼类潜艇
*/
public class TorpedoSubmarine extends SeaObject{
public TorpedoSubmarine() {
super(64,20);
}
/**
* 鱼类潜艇移动的方法
*/
@Override
public void move() {
x+=speed;
}
@Override
public ImageIcon getImage() {
return Images.torpesubm;
}
}
2.4.9World(测试类)
package cn.tedu.submarine;
import javax.swing.*;
import java.awt.Graphics;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
/**
* 整个游戏世界
*/
public class World extends JPanel {
public static final int WIDTH = 641;//窗口的宽
public static final int HEIGHT = 479;//窗口的高
private Battleship ship = new Battleship();//战舰
private SeaObject[] submarines = {};//潜艇数组(侦察潜艇,鱼雷潜艇,水雷潜艇)
private Mine[] mines = {
new Mine(200, 300)
};//水雷数组
private Bomb[] bombs = {
new Bomb(180, 130)
};//炸弹数组
public void action() {
Timer timer = new Timer();
int interval = 10;
timer.schedule(new TimerTask() {
@Override
public void run() {
submarineEnterAction();//敌人入场
minesEnterAction();//水雷入场
submarineMove();//潜艇移动
repaint();//重新画一下
}
}, interval, interval);
}
/**
* 潜艇移动
*/
public void submarineMove() {
for (int i = 0; i < submarines.length; i++) {
submarines[i].move();
}
for (int i = 0; i < bombs.length; i++) {
bombs[i].move();
}
for (int i = 0; i < mines.length; i++) {
mines[i].move();
}
}
private int mineEnterIndex = 0;//水雷入场计数
/**
* 水雷入场
*/
public void minesEnterAction() {//没10个毫秒走一次
mineEnterIndex++;//没10毫秒增1
if (mineEnterIndex % 100 == 0){
}
}
private int subEnterIndex = 0;
/**
* 敌人入场
*/
public void submarineEnterAction() {
subEnterIndex++;
if (subEnterIndex%40 == 0){
SeaObject obj = nextSubmarine();
submarines = Arrays.copyOf(submarines,submarines.length+1);
submarines[submarines.length-1]=obj;
}
}
/**
* 生成潜艇对象
*/
public SeaObject nextSubmarine() {
Random random = new Random();
int type = random.nextInt(20);
if (type < 10) {
return new ObserverSubmarine();
} else if (type < 15) {
return new TorpedoSubmarine();
} else {
return new MineSubmarine();
}
}
/**
* 重写JPanel中的paint()画 g 画笔
*
* @param g
*/
@Override
public void paint(Graphics g) {
Images.sea.paintIcon(null, g, 0, 0);//海洋图片
ship.paintImage(g);
//画敌人
for (int i = 0; i < submarines.length; i++) {
submarines[i].paintImage(g);
}
//画水雷
for (int i = 0; i < mines.length; i++) {
mines[i].paintImage(g);
}
//画炸弹
for (int i = 0; i < bombs.length; i++) {
bombs[i].paintImage(g);
}
}
public static void main(String[] args) {
JFrame frame = new JFrame();
World world = new World();
world.setFocusable(true);
frame.add(world);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(WIDTH + 16, HEIGHT + 39);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
world.action();
}
}
3.补充
3.1隐式的引用:
- this:指代当前对象
- super:指代当前对象的超类对象
- 外部类名.this:指代当前对象的外部类对象
3.2做功能的套路:
- 先写行为/方法:
- 若为某个对象所特有的行为,就将方法设计在特定的类中
- 若为所有对象所共有的行为,就将方法设计在超类中
- 窗口调用:
- 若为定时发生的,就在定时器run中调用
- 若为事件触发的,就在侦听器中调用-------------------明天讲
3.3如何调错:
- 打桩:System.out.println(数据);-----------需要慢慢来,调得多了就有经验了
3.4明日单词:
1)interface:接口
2)implements:实现
3)enemy:敌人
4)nuclear:核武器
5)left:左
6)right:右
7)out of bounds:超出界限
8)Key:键盘
9)Adapter:适配器
10)release:松开/弹起
11)code:编码
12)space:空白
13)listener:监听