笔记:
1. 内存管理:由JVM来管理
- 堆:
- 存储new出来的对象(包括实例变量、数组元素)
- 垃圾:没有任何引用所指向的对象
垃圾回收器(GC)不定时到堆中回收垃圾,回收过程是透明的(看不到的),不一定一发现垃圾就立刻回收,通过调用System.gc()建议JVM尽快调度GC来回收
- 实例变量的生命周期:
创建对象时存储在堆中,对象被回收时一并被回收
- 内存泄漏:不再使用的对象还没有被及时的回收
建议:不再使用的对象应及时将引用设置为null
![堆](C:\Users\TEDU\Desktop\ooDay10\堆.png)
- 栈:
- 存储正在调用的方法中的局部变量(包括方法的参数)
- 调用方法时会在栈中为该方法分配一块对应的栈帧,栈帧中存储局部变量(包括方法参数),方法调用结束时,栈帧被清除,局部变量一并被清除
- 局部变量的生命周期:
调用方法时存储在栈中,方法调用结束时与栈帧一并被清除
![栈](C:\Users\TEDU\Desktop\ooDay10\栈.png)
- 方法区:
- 存储.class字节码文件(包括静态变量、所有方法)
- 方法只有一份,通过this来区分具体的调用对象
![方法区](C:\Users\TEDU\Desktop\ooDay10\方法区.png)
2. 面向对象三大特征:
- 封装:
- 类:封装的是对象的属性和行为
- 方法:封装一段特定的业务逻辑功能
- 访问控制修饰符:封装的是具体的访问权限
- 继承:
- 作用:代码复用
- 超类:所有派生类共有的属性和行为
接口:部分派生类共有的属性和行为
派生类:派生类特有的属性和行为
- 单一继承、多接口实现,具有传递性
- 多态:
- 所有对象都是多态的(通过向上造型来体现)
所有抽象方法都是多态的(通过方法的重写来体现)
- 向上造型、方法重写、强制类型转换、instanceof判断
3. String:字符串类型
- java.lang.String使用final修饰,不能被继承
- java中的String采用Unicode编码格式,任何一个字符都占用两个字节
- String字符串底层封装了字符数组
- 字符串一旦创建,对象内容永远无法改变,但字符串引用可以重新赋值----不变对象
4. 常量池:
- java对字符串有一个优化措施:字符串常量池(堆中)
- java推荐我们使用字面量/直接量的方式来创建字符串,并且会缓存所有以字面量形式创建的字符串对象到常量池中,当使用相同字符量再创建字符串时会重用对象以减少内存开销,避免内存中堆积大量内容相同的字符串对象
```java
String s1 = "123abc"; //堆中创建一个123abc对象,常量池中存储这个对象的引用
//编译器在编译时,若发现是两个字面量连接,则直接运算好并将结果保存起来,
//如下代码相当于 String s2 = "123abc";
String s2 = "123"+"abc"; //复用常量池中的123abc对象
System.out.println(s1==s2); //true
String s3 = "123";
//因为s3不是字面量,所以并不会直接运算结果
//如下代码会在堆中创建新的123abc对象,而不会重用常量池中的对象
String s4 = s3+"abc";
System.out.println(s1==s4); //false
/*
使用字面量创建字符串对象时,JVM会检查常量池中是否有该对象:
1)若没有,则会创建该字符串对象并存入常量池中
2)若有,则直接将常量池中的对象地址返回(不会再创建新的字符串对象)
*/
String s1 = "123abc"; //常量池还没有,因此创建该字符串对象,并存入常量池
String s2 = "123abc"; //常量池中已经有了,直接重用对象
String s3 = "123abc"; //常量池中已经有了,直接重用对象
//引用类型==,比较的是地址是否相同 //练习-----5:10继续
System.out.println(s1==s2); //true
System.out.println(s1==s3); //true
System.out.println(s2==s3); //true
s1 = s1+"!"; //创建新的字符串对象并将地址赋值给s1
System.out.println(s1==s2); //false,因为s1为新对象的地址,与s2不同了
```
## 精华笔记:
1. 内存管理:由JVM来管理
- 堆:
- 存储new出来的对象(包括实例变量、数组元素)
- 垃圾:没有任何引用所指向的对象
垃圾回收器(GC)不定时到堆中回收垃圾,回收过程是透明的(看不到的),不一定一发现垃圾就立刻回收,通过调用System.gc()建议JVM尽快调度GC来回收
- 实例变量的生命周期:
创建对象时存储在堆中,对象被回收时一并被回收
- 内存泄漏:不再使用的对象还没有被及时的回收
建议:不再使用的对象应及时将引用设置为null
- 栈:
- 存储正在调用的方法中的局部变量(包括方法的参数)
- 调用方法时会在栈中为该方法分配一块对应的栈帧,栈帧中存储局部变量(包括方法参数),方法调用结束时,栈帧被清除,局部变量一并被清除
- 局部变量的生命周期:
调用方法时存储在栈中,方法调用结束时与栈帧一并被清除
- 方法区:
- 存储.class字节码文件(包括静态变量、所有方法)
- 方法只有一份,通过this来区分具体的调用对象
2. 面向对象三大特征:
- 封装:
- 类:封装的是对象的属性和行为
- 方法:封装一段特定的业务逻辑功能
- 访问控制修饰符:封装的是具体的访问权限
- 继承:
- 作用:代码复用
- 超类:所有派生类共有的属性和行为
接口:部分派生类共有的属性和行为
派生类:派生类特有的属性和行为
- 单一继承、多接口实现,具有传递性
- 多态:
- 所有对象都是多态的(通过向上造型来体现)
所有抽象方法都是多态的(通过方法的重写来体现)
- 向上造型、方法重写、强制类型转换、instanceof判断
3. String:字符串类型
- java.lang.String使用final修饰,不能被继承
- java中的String采用Unicode编码格式,任何一个字符都占用两个字节
- String字符串底层封装了字符数组
- 字符串一旦创建,对象内容永远无法改变,但字符串引用可以重新赋值----不变对象
4. 常量池:
- java对字符串有一个优化措施:字符串常量池(堆中)
- java推荐我们使用字面量/直接量的方式来创建字符串,并且会缓存所有以字面量形式创建的字符串对象到常量池中,当使用相同字符量再创建字符串时会重用对象以减少内存开销,避免内存中堆积大量内容相同的字符串对象
## 补充:
1. 每个对象最少具备两种形态:本身的形态+Object的形态
1. 水雷与战舰的碰撞:
参考代码:
```java
package day10;
import javax.swing.ImageIcon;
//战舰
public class Battleship extends SeaObject {
private int life;
public Battleship(){
super(66,26,270,124,20);
life = 5;
}
public void step(){
}
public ImageIcon getImage(){
return Images.battleship;
}
public Bomb shoot(){
return new Bomb(this.x,this.y);
}
public void moveLeft(){
x-=speed;
}
public void moveRight(){
x+=speed;
}
public void addLife(int life){
this.life += life;
}
public int getLife(){
return life;
}
public void subtractLife(){
life--;
}
}
package day10;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Graphics;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
//整个游戏世界
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 = {}; //水雷
private Bomb[] bombs = {}; //深水炸弹
/** 随机生成潜艇 */
public SeaObject nextOne(){
Random rand = new Random();
int type = rand.nextInt(20);
if(type<10){
return new ObserveSubmarine();
}else if(type<15){
return new TorpedoSubmarine();
}else{
return new MineSubmarine();
}
}
private int subEnterIndex = 0;
/** 潜艇入场 */
public void submarineEnterAction(){ //每10毫秒走一次
subEnterIndex++;
if(subEnterIndex%40==0){ //每400毫秒
SeaObject obj = nextOne();
submarines = Arrays.copyOf(submarines,submarines.length+1);
submarines[submarines.length-1] = obj;
}
}
private int mineEnterIndex = 0;
/** 雷(鱼雷、水雷)入场 */
public void MineEnterAction(){
mineEnterIndex++;
if(mineEnterIndex%100==0){
for(int i=0;i<submarines.length;i++){
if(submarines[i] instanceof MineSubmarine){
MineSubmarine ms = (MineSubmarine)submarines[i];
Mine obj = ms.shootMine();
mines = Arrays.copyOf(mines,mines.length+1);
mines[mines.length-1] = obj;
}
}
}
}
/** 海洋对象移动 */
public void moveAction(){
for(int i=0;i<submarines.length;i++){
submarines[i].move();
}
for(int i=0;i<mines.length;i++){
mines[i].move();
}
for(int i=0;i<bombs.length;i++){
bombs[i].move();
}
}
/** 删除越界的对象 */
public void outOfBoundsAction(){
for(int i=0;i<submarines.length;i++){
if(submarines[i].isOutOfBounds() || submarines[i].isDead()){
submarines[i] = submarines[submarines.length-1];
submarines = Arrays.copyOf(submarines,submarines.length-1);
}
}
for(int i=0;i<mines.length;i++){
if(mines[i].isOutOfBounds() || mines[i].isDead()){
mines[i] = mines[mines.length-1];
mines = Arrays.copyOf(mines,mines.length-1);
}
}
for(int i=0;i<bombs.length;i++){
if(bombs[i].isOutOfBounds() || bombs[i].isDead()){
bombs[i] = bombs[bombs.length-1];
bombs = Arrays.copyOf(bombs,bombs.length-1);
}
}
}
private int score = 0; //玩家得分
//深水炸弹与潜艇的碰撞
public void bombBangAction(){
for(int i=0;i<bombs.length;i++){
Bomb b = bombs[i];
for(int j=0;j<submarines.length;j++){
SeaObject s = submarines[j];
if(b.isLive() && s.isLive() && s.isHit(b)){
b.goDead();
s.goDead();
if(s instanceof EnemyScore){
EnemyScore es = (EnemyScore)s;
score += es.getScore();
}
if(s instanceof EnemyLife){
EnemyLife ea = (EnemyLife)s;
int life = ea.getLife();
ship.addLife(life);
}
}
}
}
}
//水雷与战舰的碰撞
public void mineBangAction(){
for(int i=0;i<mines.length;i++){
Mine m = mines[i];
if(m.isLive() && ship.isLive() && m.isHit(ship)){
m.goDead();
ship.subtractLife();
}
}
}
/** 启动程序的运行 */
public void action(){
KeyAdapter k = new KeyAdapter(){
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_SPACE){
Bomb obj = ship.shoot(); //深水炸弹入场
bombs = Arrays.copyOf(bombs,bombs.length+1);
bombs[bombs.length-1] = obj;
}
if(e.getKeyCode() == KeyEvent.VK_LEFT){
ship.moveLeft();
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT){
ship.moveRight();
}
}
};
this.addKeyListener(k);
Timer timer = new Timer();
int interval = 10;
timer.schedule(new TimerTask() {
public void run() {
submarineEnterAction(); //潜艇(侦察、水雷、鱼雷)入场
MineEnterAction(); //水雷入场
moveAction(); //海洋对象移动
outOfBoundsAction(); //删除越界的对象
bombBangAction(); //深水炸弹与潜艇的碰撞
mineBangAction(); //水雷与战舰的碰撞
repaint();
}
}, interval, interval);
}
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);
}
g.drawString("SCORE: "+score,200,50);
g.drawString("LIFE: "+ship.getLife(),400,50);
}
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();
}
}
2. 检测游戏结束:
参考代码:
```java
package day10;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Graphics;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
//整个游戏世界
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 = {}; //水雷
private Bomb[] bombs = {}; //深水炸弹
/** 随机生成潜艇 */
public SeaObject nextOne(){
Random rand = new Random();
int type = rand.nextInt(20);
if(type<10){
return new ObserveSubmarine();
}else if(type<15){
return new TorpedoSubmarine();
}else{
return new MineSubmarine();
}
}
private int subEnterIndex = 0;
/** 潜艇入场 */
public void submarineEnterAction(){ //每10毫秒走一次
subEnterIndex++;
if(subEnterIndex%40==0){ //每400毫秒
SeaObject obj = nextOne();
submarines = Arrays.copyOf(submarines,submarines.length+1);
submarines[submarines.length-1] = obj;
}
}
private int mineEnterIndex = 0;
/** 雷(鱼雷、水雷)入场 */
public void MineEnterAction(){
mineEnterIndex++;
if(mineEnterIndex%100==0){
for(int i=0;i<submarines.length;i++){
if(submarines[i] instanceof MineSubmarine){
MineSubmarine ms = (MineSubmarine)submarines[i];
Mine obj = ms.shootMine();
mines = Arrays.copyOf(mines,mines.length+1);
mines[mines.length-1] = obj;
}
}
}
}
/** 海洋对象移动 */
public void moveAction(){
for(int i=0;i<submarines.length;i++){
submarines[i].move();
}
for(int i=0;i<mines.length;i++){
mines[i].move();
}
for(int i=0;i<bombs.length;i++){
bombs[i].move();
}
}
/** 删除越界的对象 */
public void outOfBoundsAction(){
for(int i=0;i<submarines.length;i++){
if(submarines[i].isOutOfBounds() || submarines[i].isDead()){
submarines[i] = submarines[submarines.length-1];
submarines = Arrays.copyOf(submarines,submarines.length-1);
}
}
for(int i=0;i<mines.length;i++){
if(mines[i].isOutOfBounds() || mines[i].isDead()){
mines[i] = mines[mines.length-1];
mines = Arrays.copyOf(mines,mines.length-1);
}
}
for(int i=0;i<bombs.length;i++){
if(bombs[i].isOutOfBounds() || bombs[i].isDead()){
bombs[i] = bombs[bombs.length-1];
bombs = Arrays.copyOf(bombs,bombs.length-1);
}
}
}
private int score = 0; //玩家得分
//深水炸弹与潜艇的碰撞
public void bombBangAction(){
for(int i=0;i<bombs.length;i++){
Bomb b = bombs[i];
for(int j=0;j<submarines.length;j++){
SeaObject s = submarines[j];
if(b.isLive() && s.isLive() && s.isHit(b)){
b.goDead();
s.goDead();
if(s instanceof EnemyScore){
EnemyScore es = (EnemyScore)s;
score += es.getScore();
}
if(s instanceof EnemyLife){
EnemyLife ea = (EnemyLife)s;
int life = ea.getLife();
ship.addLife(life);
}
}
}
}
}
//水雷与战舰的碰撞
public void mineBangAction(){
for(int i=0;i<mines.length;i++){
Mine m = mines[i];
if(m.isLive() && ship.isLive() && m.isHit(ship)){
m.goDead();
ship.subtractLife();
}
}
}
/** 检测游戏结束 */
public void checkGameOverAction(){
if(ship.getLife()<=0){
......
}
}
/** 启动程序的运行 */
public void action(){
KeyAdapter k = new KeyAdapter(){
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_SPACE){
Bomb obj = ship.shoot();
bombs = Arrays.copyOf(bombs,bombs.length+1);
bombs[bombs.length-1] = obj;
}
if(e.getKeyCode() == KeyEvent.VK_LEFT){
ship.moveLeft();
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT){
ship.moveRight();;
}
}
};
this.addKeyListener(k);
Timer timer = new Timer();
int interval = 10;
timer.schedule(new TimerTask() {
public void run() {
submarineEnterAction(); //潜艇(侦察、水雷、鱼雷)入场
MineEnterAction(); //水雷入场
moveAction(); //海洋对象移动
outOfBoundsAction(); //删除越界的对象
bombBangAction(); //深水炸弹与潜艇的碰撞
mineBangAction(); //水雷与战舰的碰撞
checkGameOverAction(); //检测游戏结束
repaint();
}
}, interval, interval);
}
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);
}
g.drawString("SCORE: "+score,200,50);
g.drawString("LIFE: "+ship.getLife(),400,50);
}
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. 画状态:
参考代码:
```java
package cn.tedu.submarine;
import javax.swing.JFrame;
import javax.swing.JPanel; //1.
import java.awt.Graphics;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
/** 整个游戏世界 */
public class World extends JPanel { //2.
public static final int WIDTH = 641; //窗口的宽
public static final int HEIGHT = 479; //窗口的高
public static final int RUNNING = 0; //运行状态
public static final int PAUSE = 1; //暂停状态
public static final int GAME_OVER = 2; //游戏结束状态
private int state = RUNNING; //当前状态(默认为运行状态)
//如下这一堆为窗口中所显示的对象
private Battleship ship = new Battleship(); //战舰
private SeaObject[] submarines = {}; //潜艇(侦察潜艇、鱼雷潜艇、水雷潜艇)数组
private Mine[] mines = {}; //水雷数组
private Bomb[] bombs = {}; //深水炸弹数组
/** 生成潜艇(侦察潜艇、鱼雷潜艇、水雷潜艇)对象 */
private SeaObject nextSubmarine(){
Random rand = new Random(); //随机数对象
int type = rand.nextInt(20); //0到19之间
if(type<10){ //0到9时,返回侦察潜艇
return new ObserveSubmarine();
}else if(type<15){ //10到14时,返回鱼雷潜艇
return new TorpedoSubmarine();
}else{ //15到19时,返回水雷潜艇
return new MineSubmarine();
}
}
private int subEnterIndex = 0; //潜艇入场计数
/** 潜艇(侦察潜艇、鱼雷潜艇、水雷潜艇)入场 */
private void submarineEnterAction(){ //每10毫秒走一次
subEnterIndex++; //每10毫秒增1
if(subEnterIndex%40==0){ //每400(40*10)毫秒走一次
SeaObject obj = nextSubmarine(); //获取潜艇对象
submarines = Arrays.copyOf(submarines,submarines.length+1); //扩容
submarines[submarines.length-1] = obj; //将obj添加到submarines最后一个元素上
}
}
private int mineEnterIndex = 0; //水雷入场计数
/** 水雷入场 */
private void mineEnterAction(){ //每10毫秒走一次
mineEnterIndex++; //每10毫秒增1
if(mineEnterIndex%100==0){ //每1000(100*10)毫秒走一次
for(int i=0;i<submarines.length;i++){ //遍历所有潜艇
if(submarines[i] instanceof MineSubmarine){ //若潜艇为水雷潜艇
MineSubmarine ms = (MineSubmarine)submarines[i]; //将潜艇强转为水雷潜艇
Mine obj = ms.shootMine(); //获取水雷对象
mines = Arrays.copyOf(mines,mines.length+1); //扩容
mines[mines.length-1] = obj; //将obj添加到mines最后一个元素上
}
}
}
}
/** 海洋对象移动 */
private void moveAction(){ //每10毫秒走一次
for(int i=0;i<submarines.length;i++){ //遍历所有潜艇
submarines[i].move(); //潜艇移动
}
for(int i=0;i<mines.length;i++){ //遍历所有水雷
mines[i].move(); //水雷移动
}
for(int i=0;i<bombs.length;i++){ //遍历所有深水炸弹
bombs[i].move(); //深水炸弹移动
}
}
/** 删除越界的海洋对象----避免内存泄漏 */
private void outOfBoundsAction(){ //每10毫秒走一次
for(int i=0;i<submarines.length;i++){ //遍历所有潜艇
if(submarines[i].isOutOfBounds() || submarines[i].isDead()){ //越界的,或者死了的
submarines[i] = submarines[submarines.length-1]; //将越界潜艇替换为最后一个元素
submarines = Arrays.copyOf(submarines,submarines.length-1); //缩容
}
}
for(int i=0;i<mines.length;i++){ //遍历所有水雷
if(mines[i].isOutOfBounds() || mines[i].isDead()){ //越界的,或者死了的
mines[i] = mines[mines.length-1]; //将越界水雷替换为最后一个元素
mines = Arrays.copyOf(mines,mines.length-1); //缩容
}
}
for(int i=0;i<bombs.length;i++){ //遍历所有深水炸弹
if(bombs[i].isOutOfBounds() || bombs[i].isDead()){ //越界的,或者死了的
bombs[i] = bombs[bombs.length-1]; //将越界深水炸弹替换为最后一个元素
bombs = Arrays.copyOf(bombs,bombs.length-1); //缩容
}
}
}
private int score = 0; //玩家得分
/** 深水炸弹与潜艇的碰撞 */
private void bombBangAction(){ //每10毫秒走一次
for(int i=0;i<bombs.length;i++){ //遍历所有炸弹
Bomb b = bombs[i]; //获取每个炸弹
for(int j=0;j<submarines.length;j++){ //遍历所有潜艇
SeaObject s = submarines[j]; //获取每个潜艇
if(b.isLive() && s.isLive() && s.isHit(b)){ //若都活着并且还撞上了
s.goDead(); //潜艇去死
b.goDead(); //炸弹去死
if(s instanceof EnemyScore){ //若被撞对象为分
EnemyScore es = (EnemyScore)s; //将被撞对象强转为得分接口
score += es.getScore(); //玩家得分
}
if(s instanceof EnemyLife){ //若被撞对象为命
EnemyLife el = (EnemyLife)s; //将被撞对象强转为得命接口
int num = el.getLife(); //获取命数
ship.addLife(num); //战舰增命
}
}
}
}
}
/** 水雷与战舰的碰撞 */
private void mineBangAction(){ //每10毫秒走一次
for(int i=0;i<mines.length;i++){ //遍历所有水雷
Mine m = mines[i]; //获取每个水雷
if(m.isLive() && ship.isLive() && ship.isHit(m)){ //若都活着并且还撞上了
m.goDead(); //水雷去死
ship.subtractLife(); //减命
}
}
}
/** 检测游戏结束 */
private void checkGameOverAction(){ //每10毫秒走一次
if(ship.getLife()<=0){ //若战舰的命数<=0,表示游戏结束了
state = GAME_OVER; //将当前状态修改为GAME_OVER游戏结束状态
}
}
/** 启动程序的执行 */
private void action(){
KeyAdapter k = new KeyAdapter() { //不要求掌握
/** 重写keyReleased()按键弹起事件 */
public void keyReleased(KeyEvent e) { //不要求掌握--当按键弹起时会自动触发
if(e.getKeyCode()==KeyEvent.VK_P){ //不要求掌握--若按键是P键
if(state==RUNNING){ //运行状态时修改为暂停状态
state = PAUSE;
}else if(state==PAUSE){ //暂停状态时修改为运行状态
state = RUNNING;
}
}
if(state!=RUNNING){ //若当前状态不是运行状态
return; //则结束事件处理
}
if(e.getKeyCode() == KeyEvent.VK_SPACE){ //不要求掌握--若按键是空格键
Bomb obj = ship.shootBomb(); //获取深水炸弹对象
bombs = Arrays.copyOf(bombs,bombs.length+1); //扩容
bombs[bombs.length-1] = obj; //将深水炸弹添加到bombs的最后一个元素上
}
if(e.getKeyCode() == KeyEvent.VK_LEFT){ //不要求掌握--若按键是左键头
ship.moveLeft(); //战舰左移
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT){ //不要求掌握--若按键是右键头
ship.moveRight(); //战舰右移
}
}
};
this.addKeyListener(k); //不要求掌握
Timer timer = new Timer(); //定时器对象
int interval = 10; //定时间隔(以毫秒为单位)
timer.schedule(new TimerTask() {
public void run() { //定时干的事(每10毫秒自动执行)
if(state==RUNNING){ //仅在运行状态时执行
submarineEnterAction(); //潜艇(侦察潜艇、鱼雷潜艇、水雷潜艇)入场
mineEnterAction(); //水雷入场
moveAction(); //海洋对象移动
outOfBoundsAction(); //删除越界的海洋对象
bombBangAction(); //深水炸弹与潜艇的碰撞
mineBangAction(); //水雷与战舰的碰撞
checkGameOverAction(); //检测游戏结束
}
repaint(); //重新调用paint()方法----不要求掌握
}
}, interval, interval); //日程表
}
/** 重写JPanel类中的paint()方法 g:画笔 */ //只需要知道想画东西需要重写paint()即可
public void paint(Graphics g){ //每10毫秒走一次
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);
}
g.drawString("SCORE: "+score,200,50); //不要求掌握--画分
g.drawString("LIFE: "+ship.getLife(),400,50); //不要求掌握--画命
if(state==GAME_OVER){ //若当前状态为游戏结束状态
Images.gameover.paintIcon(null,g,0,0); //画游戏结束图---不要求掌握
}
}
public static void main(String[] args) {
JFrame frame = new JFrame(); //3.
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); //自动调用paint()方法
world.action();
}
}
4. String基本练习:
声明最少三个字符串型变量并直接赋值,使用==比较三个变量是否相等,修改其中一个变量的值,
使用==比较修改后的变量与其它两个变量是否相等。
参考代码:
```java
/*
使用字面量创建字符串对象时,JVM会检查常量池中是否有该对象:
1)若没有,则会创建该字符串对象并存入常量池中
2)若有,则直接将常量池中的对象地址返回(不会再创建新的字符串对象)
*/
String s1 = "123abc"; //常量池还没有,因此创建该字符串对象,并存入常量池
String s2 = "123abc"; //常量池中已经有了,直接重用对象
String s3 = "123abc"; //常量池中已经有了,直接重用对象
//引用类型==,比较的是地址是否相同 //练习-----5:10继续
System.out.println(s1==s2); //true
System.out.println(s1==s3); //true
System.out.println(s2==s3); //true
s1 = s1+"!"; //创建新的字符串对象并将地址赋值给s1
System.out.println(s1==s2); //false,因为s1为新对象的地址,与s2不同了
String s1 = "123abc"; //堆中创建一个123abc对象,常量池中存储这个对象的引用
//编译器在编译时,若发现是两个字面量连接,则直接运算好并将结果保存起来,
//如下代码相当于 String s2 = "123abc";
String s2 = "123"+"abc"; //复用常量池中的123abc对象
System.out.println(s1==s2); //true
String s3 = "123";
//因为s3不是字面量,所以并不会直接运算结果
//如下代码会在堆中创建新的123abc对象,而不会重用常量池中的对象
String s4 = s3+"abc";
System.out.println(s1==s4); //false