初学Java第十六天

笔记

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

   

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值