1. static final常量:应用率高
- 必须声明同时初始化
- 由类名点来访问,不能被改变
- 建议:常量名所有字母都大写,多个单词用_分隔
- 编译器在编译时会将常量直接替换为具体的值,效率高
- 何时用:数据永远不变,并且经常使用
public class StaticFinalDemo {
public static void main(String[] args) {
System.out.println(Aoo.PI); //常常通过类名点来访问
//Aoo.PI = 3.14159; //编译错误,常量不能被改变
//1)加载Boo.class到方法区中
//2)静态变量num一并存储到方法区中
//3)到方法区中获取num的值并输出
System.out.println(Boo.num);
//编译器在编译时会将常量直接替换为具体的值,效率高
//如下语句相当于:System.out.println(5);
System.out.println(Boo.COUNT);
}
}
//演示常量的特点
class Boo{
public static int num = 5; //静态变量
public static final int COUNT = 5; //常量
}
//演示常量的语法
class Aoo{
public static final double PI = 3.14;
//public static final int NUM; //编译错误,常量必须声明同时初始化
}
2.抽象:abstract
2.1抽象方法
- 由abstract修饰
- 只有方法的定义,没有具体的实现(连{}都没有)
2.2抽象类
- 由abstract修饰
- 包含抽象方法的类必须是抽象类
- 抽象类不能被实例化(new对象)
- 抽象类是需要被继承的,派生类:
- 重写所有抽象方法-----------------变不完整为完整
- 也声明为抽象类--------------------一般不这么做
- 抽象类的意义:
- 封装共有的属性和行为---------------代码复用
- 为所有派生类提供统一的类型------向上造型(代码复用)
- 可以包含抽象方法,为所有派生类提供统一的入口(能点出来),同时达到强制必须重写的目的(相当于制定了一个标准)
3.潜艇游戏第六天:
- 设置窗口的宽和高为常量,适当地方做修改
- 画对象:(需求)
1)想画对象需要获取对象的图片,每个对象都能获取图片,
意味着获取图片行为为共有的行为,所以设计在SeaObject超类中,
每个对象获取图片的行为都是不一样的,所以设计为抽象方法
---在SeaObject中设计抽象方法getImage()获取对象的图片
2)重写getImage()获取对象的图片
---在6个类中重写getImage()返回对应的图片
3)因为只有活着的对象才需要画到窗口中,所以需要设计对象的状态,
每个对象都有状态,意味着状态为共有属性,所以设计在SeaObject超类中,
状态一般都设计为常量,同时设计state变量表示当前状态
---在SeaObject中设计状态常量LIVE、DEAD,state变量表示当前状态
在后期的业务中经常需要判断对象的状态,每个对象都能判断,
意味着判断状态的行为为共有行为,所以设计在SeaObject中,
每个对象判断状态的行为都是一样的,所以设计为普通方法
---在SeaObject中设计isLive()、isDead()判断对象状态
4)数据(状态、图片、x坐标、y坐标)都有了就可以开画了,每个对象都能画,
意味着画对象行为为共有行为,所以设计在SeaObject超类中,
每个对象画的行为都是一样的,所以设计为普通方法
---在SeaObject中设计paintImage()画图片------具体怎么画,不要求掌握
5)画图片的行为做好了,在窗口World类中调用即可
5.1)准备对象
5.2)重写paint()方法------调用paintImage()完成画图片的功能
3.1.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(){
}
}
3.1.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;
}
}
3.1.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());
// }
}
3.1.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;
}
}
3.1.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;
}
}
3.1.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;
}
}
3.1.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);
}
}
}
3.1.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;
}
}
3.1.9World(测试类)
package cn.tedu.submarine;
import javax.swing.*;
import java.awt.Graphics;
/**
* 整个游戏世界
*/
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 = {
new ObserverSubmarine(),
new MineSubmarine(),
new TorpedoSubmarine()
};//潜艇数组(侦察潜艇,鱼雷潜艇,水雷潜艇)
private Mine[] mines = {
new Mine(200,300)
};//水雷数组
private Bomb[] bombs = {
new Bomb(180,130)
};//炸弹数组
/**
* 重写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);
}
}
4.补充
4.1访问权限由大到小依次为:
- public > protected > 默认的 > private
4.2设计规则:
- 将派生类所共有的属性和行为,抽到超类中------------------抽共性
- 若对象的行为都一样,设计为普通方法
- 若对象的行为都不一样,设计为抽象方法
4.3抽象方法/抽象类的疑问:
- 抽象方法存在的意义是什么?
- 保证当发生向上造型时,通过超类的引用能点出来那个方法
- 既然意义只在于能点出来,那为什么不设计成普通方法呢?
- 若设计为普通方法,则派生类可以重写也可以不重写,而设计为抽象方法,则可以强制派生类必须重写------做了个标准,强制必须重写