java面向对象(OOP)知识点

目录

*方法:函数、过程**

1、方法:

2、 方法的定义:五要素

3、方法的调用:

面向对象

1、什么是类?什么是对象?

2、如何创建类?如何创建类?如何访问成员?

类:是一种数据类型(引用类型)

射击游戏

方法签名:方法名+参数列表

3、方法的重载 (overload)-----------------------可以大大的简化方法的访问

4、构造方法:构造函数、构造器、构建

 5、this:指代当前对象,哪个对象调用方法它指的就是那个对像

6、null 和 NullPointerException

2021-6-9(引用类型数组,继承,super)

1、引用类型数组

2、继承

3、super:指代当前对象的超类对象

4、数组的赋值:

2021-6-10

1、向上造型:

2、方法的重写(override):重新写、覆盖

2021-6-11

1、重写与重载的区别:

2、package 和 import:

3、访问控制修饰符:-----------------访问控制的权限,保护数据的安全

4、final:最终的、不可改变的-------------单独应用几率低

5、static:静态的

2021-6-15

1、static final 常量:

2、抽象方法:

3、抽象类:

2021-6-16

1、画对象

2、成员内部类:

3、匿名内部类:------------------便于访问数据

Shoot射击游戏第八天

如何调错:

2020-6-18

1、接口:

设计规则:

2、多态:------------------多种形态

2021-6-21

get/set的用法:

内存管理:由JVM来管理

面向对象总结


*方法:函数、过程**

1、方法

1)封装一段特定的业务逻辑功能
2)方法尽可能独立,一个方法只干一件事
3)反复多次使用
4)减少代码重复,有利于代码的维护

2、 方法的定义:五要素

修饰词  返回值类型    方法名(参数列表){
    方法体
}

3、方法的调用:

public class MethodDemo {
    public static void main(String[] args) {
        say();
        sayHi("WMZ");
    }
    //有参无返回值
    public static void sayHi(String name){
        System.out.println("Hello,My name is "+name+",I am 38 years old");
    }
    //无参无返回值
    public static void say(){
        System.out.println("Hello,My name is SSM,I am 38 years old");
    }
}

面向对象

OO:面向对象
OOA:面向对象分析
OOD:面向对象设计
OOP:面向对象编程
    
面向对象:----难(比较抽象)
        ----很多的东西,不这么写也行,但这样写一定是最好的

高质量代码:
    复用性好、扩展性好、维护性好、可移植性好、健壮性好、可读性好、效率好...

1、什么是类?什么是对象?

1)现实世界是由很多的对象组成的
2)对象:真实存在的东西/个体
  类:类型/类别,代表一类个体
3)类是对象的模版,对象是类的具体的实例
4)类可以包含:
  4.1)对象所共用的属性/特征---------变量
  4.2)对象所共用的行为/动作---------方法
5)一个类可以创建多个对象

2、如何创建类?如何创建类?如何访问成员?

数据类型 引用类型变量 指向   对象
Student    zs       =   new Student();
Student zs = new Student();
Student ls = new Student();
Student ww = new Student();

类:是一种数据类型(引用类型)

class Airplane{ //小敌机类   
    int width;    
    int height;    
    int x;    
    int y;        
    void step(){ //移动   
    }    
    void bangBullet(){  //和子弹撞    
    }    
    void bangHero(){  //和英雄机撞    
    }
}  
air1Width,air1Height,air1X,air1Y  
air2Width,air2Height,air2X,air2Y  
air3Width,air3Height,air3X,air3Y  
...  
air100Width,air100Height,air100X,air100Y
​class BigAirplane{
}
class Bee{
}
...

射击游戏

射击游戏需求:
 1、所参与的角色:英雄机、子弹、小敌机、大敌机、小蜜蜂、天空
 2、角色间的关系:
    1)英雄机发射子弹(单倍火力、双倍火力)
    2)子弹可以射击敌人(小敌机、大敌机、小蜜蜂),若击中了;
      2.1)子弹直接消失、敌人先爆破再消失
      2.2)若击中的是小敌机,则玩家得1分
          若击中的是大敌机,则玩家得3分
          若击中的是小蜜蜂,则英雄机得奖励(1条命或40火力值)
    3)敌人(小敌机、大敌机、小蜜蜂)和英雄机相撞,若撞上了:
      3.1)敌人先爆破再消失
      3.2)英雄机减1条命,同时,清空火力值
        ------当英雄机命数为0时,游戏结束
    4)英雄机、子弹、小敌机、大敌机、小蜜蜂都在天空上飞

Hero: 		 width,height,x,y,step(),	life,fire
Airplane:	 width,height,x,y,step(),	speed
BigAiplane:	 width,height,x,y,step(),	speed
Bee:		 width,height,x,y,step(),	xSpeed,ySpeed,awardType
Bullet:		 width,height,x,y,step(),	speed
Sky:		 width,height,x,y,step(), 	speed,y1
class Hero{//英雄机类    宽、高、x坐标、y坐标、命、火力值	
    void shoot(){//英雄机发射子弹    
    }    
    void step(){//切换图片    
    }    
    void move(){//随着鼠标移动    
    }
}
class Airplane{//小敌机类	宽、高、x坐标、y坐标、speed移动速度     
    void step(){        y向下动    
    }
}
class BigAirplane(){//大敌机类	同 Airplane 类
}
class Bullet{//子弹类	
    void step(){        y向上移动    
    }
}
class Bee{//蜜蜂类    宽、高、x坐标、y坐标、xSpeed移动速度、ySpeed移动速度、奖励类型                    
    void step(){        x、y坐标均移动   
    }
}
class Sky{//天空类    宽、高、x坐标、y坐标、speed移动速度、第二张天空图的坐标
}

方法签名:方法名+参数列表

3、方法的重载 (overload)-----------------------可以大大的简化方法的访问

  • 发生在同一个类中,方法名相同,参数列表不同

  • 编译器在编译的时候会根据方法的签名自动绑定调用的方法

  • public class Aoo {
        void show(){
            System.out.println("正在进行展示....");
        }
        void show(String name){
            System.out.println(name+"正在进行展示....");
        }
        void show(int age){
            System.out.println(age+"岁,已经进行展示.....");
        }
        void show(String name,int age){
            System.out.println(name+"在"+age+"岁的时候已经开始表演了.....");
        }
        void show(int age,String name){
            System.out.println(name+"在"+age+"岁的时候已经开始表演了.....");
        }
        
        //int show(){return 1; } //编译错误,重载与返回值无关
        //void show(String adress){}  //编译错误,重载与参数名称无关
    }

    4、构造方法:构造函数、构造器、构建

  • 给成员变量赋初值

  • 与类同名,没有返回值类型(连void都没有)

  • 在创建(new)对象时被自动调用

  • 若自己不写构造方法,则编译器默认提供一个无参构造方法

    若自己写了构造方法,则不再默认提供

构造方法可以重载

class Student{
    String name;
    int age;
    String address;
    Studnet(){
    }
    //给成员变量赋初值
    Student(String name1,int age1,String address1){
        name = name1;
        age = age1;
        address = address1;
    }
}
/*1、创建一个学生对象
  2、给成员变量赋默认值
  3、调用 Student 构造方法
*/
Student zs = new Student();
Student zs = new Student("zhangsan",25,"LF");
Studnet ls = new Student("lisi",26,"JMS");

 5、this:指代当前对象,哪个对象调用方法它指的就是那个对像

     只能用在方法中,方法中访问成员变量之前默认有个 this.

this的用法:

1)this.成员变量名---------------访问成员变量(当成员变量与局部变量同名时,访问成员变量时this不能省略)

2)this.方法名()----------------调用方法(一般不用)

3)this()-----------------------调用构造方法(一般不用)

 规定:

1)成员变量和局部变量是可以同名的   --------使用时默认采取的是就近原则

2)当成员变量与局部变量同名时:   ------若想访问成员变量,此时this不能省略


Student zs = new Student("周星星",19,"北京海淀");//调用方法
zs.study();
zs.sayHi();
class Student {    
    String name;	//成员变量(作用于整个类)    
    int age;    
    String address;    
    Student(String name1,int age1,String address1){  //局部变量(作用于当前方法中)        
        this.name = name1;	//zs.name = "天龙人"        
        this.age = age1;	//zs.age = 19        
        this.address = address1;	//zs.address = "北京海淀"    
    }        
    void study(){        
        System.out.println(this.name+"正在划水...");   
    }   
    void sayHi(){       
        System.out.println("大家好,我叫"+this.name+",今年"+this.age+"岁了,家住"+this.address);    	
    }
}
zs.study();----------------------study()中的this指的是zs
ls.study();----------------------study()中的this指的是ls

6、null 和 NullPointerException

内存管理:

由JVM来管理

1)堆:new 出来的对象(包括成员变量)

2)栈:局部变量(包括方法的参数)

3)方法区:

 

  null:表示空,没有指向任何对象

  • 若引用的值为null,则该引用不能再进行点操作
  • 若操作则发生NullPointerException空指针异常

2021-6-9(引用类型数组,继承,super)

1、引用类型数组

基本数据类型图示:

 

** 引用数据类型图示:**

 

int[] arr = new int[3];	//基本数据类型

Student[] stus = new Student[3];	//引用类型数组
Airplane[] as = new Airplane[10];	//引用类型数组


//声明int型数组arr,包含10个元素,每个元素都是int型,默认值为 0
int[] arr = new int[10];
arr[0] = 100;
System,out,println(arr[0]);

//声明Student型数组stus,包含3个元素,每个元素都是Student型,默认值为 null
(1)Student[] stus = new Students[3];	//创建Student数组对象
	stus[0] = new Stuent("张三",25,"北京海淀");		//创建Student对象
	stus[1] = new Student("李四",20,"打不咧爹");
	stus[2] = new Student("李四真",36,"四岔");
	System.out.println(stus[0].name)	//输出第一个学生的名字
	stus[1].age = 27;	//修改第2个学生的年龄为27
	stus[2].sayHi()		//第3个学生跟大家问好
	for(int i=0;i<stus.length;i++){	//遍历所有学生
    	System.out.println(stus[i].name); //输出每个学生的名字
    	stus[i].sayHi();	//每个学生跟大家问好
	}    
    
	//声明Airplane型数组as,包含20个元素,每个元素都是Airplane型,默认值为 null
	Airplane[] as = new Airplane[20];
	Bee[] bs = new Bee[50];
(2)另一个定义方法:
Student[] stus = new Student[]{
    new Stuent("张三",25,"北京海淀");
    new Student("李四",20,"打不咧爹");
    new Student("李四真",36,"四岔");
}
引用数组类型的实例使用:
//学生类
public class Student {
    //成员变量
    String name;
    int age;
    String address;

    Student(){
        this("天龙额额",19,"北京朝阳");//this调用构造方法
    }
    //构造方法
    Student(String name,int age,String address){
        this.name = name;
        this.age = age;
        this.address = address;
    }

    //方法
    void study(){
        System.out.println(name+" 正在努力学生...");
    }
    void sayHi(){
        System.out.println("大家好,我叫"+name+",今年"+age+"岁了,家住"+address);
    }
    /*重写toString方法*/
    public String toString(){
        return "姓名:"+name+" 年龄:"+age+" 家庭地址:"+address+"\t";
    }
}

/*引用类型数组的演示 */
public class RefArrayDemo {
    public static void main(String[] args) {
        Student[] stus = new Student[3];
        stus[0] = new Student("张三",25,"北京海淀");
        stus[1] = new Student("李四",20,"浙江杭州");
        stus[2] = new Student("李四真",36,"四岔");

        System.out.println("第一个学生的姓名为:"+stus[0].name);
        System.out.println("第一个学生的年龄为:"+stus[0].age);
        System.out.println("第一个学生的地址为:"+stus[0].address);

        stus[1].name = "周星星";   //修改第二个学生的名字


        for(int i=0;i<stus.length;i++){ //遍历所有学生
            System.out.print("学生的姓名为:"+stus[i].name+" ");
            System.out.print("学生的年龄为:"+stus[i].age+" ");
            System.out.print("学生的地址为:"+stus[i].address+"\n");
            stus[i].study();
            stus[i].sayHi();
            System.out.println();
        }

        System.out.println(Arrays.toString(stus));  //在Student中重写toString()方法,直接输出数组
    }
}

public class RefArrayDemo2 {
    public static void main(String[] args) {
        Student[] stus = new Student[]{
            new Student("张三",25,"北京海淀"),
            new Student("李四",20,"浙江杭州"),
            new Student("李四真",36,"四岔")
        };


        for(int i=0;i<stus.length;i++){
            System.out.println("学生的姓名为: "+stus[i].name+" 年龄为: "+stus[i].age+" 地址为中: "+stus[i].address);
            stus[i].study();
            stus[i].sayHi();
            System.out.println();
        }

    }
}

2、继承

  • 代码不用自己写,自己也能用

1)作用:代码复用
2)通过extends 继承
3)超类/父类: 派生类所共有的属性和行为   派生类/子类: 派生类所特有的属性和行为
4)派生类可以访问: 派生类+超类的,但超类的只能访问超类的
5)一个超类可以有多个超类,一个派生类只能有一个超类---------单一继承
6)继承具有传递性
7)java规定:构造派生类之前必须先构造超类   
    7.1) 在派生类的构造方法中,若没有调用构造方法        ---------则编译器默认super()调用超类的无参构造方法       7.2)在派生类的构造方法中,若自己调用了超类的构造方法        ---------则不再默认提供  
注意:super()调用超类的构造方法,必须位于派生类构造方法的第一行

//继承class Person{	//----------------------超类/父类    
    String name;    
    int age;    
    String address;    
    void eat(){}    
    void sleep(){}
}
class Student extends Person{	//---------------派生类/子类    
    String stuId;    
    void study(){}    
}
class Teacher extends Person{	//---------------派生类/子类    
    double salary;    
    void teach(){}
}
class Docter extends Person{	//---------------派生类/子类    
    String level;    
    void cut(){}
}
Student zs = new Student();
zs.stuId/study();
zs.name/age/address/eat()/sleep();
Teacher ls = new Teacher();
ls.salary/teach();ls.name/age/address/eat()/sleep();
//-----继承具有传递性: 
class Aoo{	//------------------Aoo只能访问变量 a    
    int a;
}
class Boo extends Aoo{	//--------------Boo可以访问变量 a,b    
    int b;
}
class Coo extends Boo{	//--------------Coo可以访问变量 a,b,c   
    int c;
}继承-----------代码虽然我没有写,但是也属于我,只是没有写在一起而已

3、super:指代当前对象的超类对象

1)super.成员变量名-------------------------访问超类的变量
2)super.方法名()---------------------------调用超类的方法
3)super()---------------------------------调用超类的构造方法

4、数组的赋值:

 FlyingObject[] ememies;FlyingObject[] ememies = null;    //两种写法一样,null,会报空指针异常
FlyingObject[] ememies = {};FlyingObject[] ememies = new FlyingObject[0];    //两种写法一样,0个元素

2021-6-10

1、向上造型:

  •  超类型的引用指向派生类的对象

超类             派生类Animal o3 = new  Tiger()Person p1 = new  Student()

  •  能点出来什么,看引用的类型---------------这是规定

超类             派生类Animal o3 = new  Tiger()o3.只能点出Animal类中的

//一个动物对象是动物类型的
Animal o1 = new Animal();
//一个老虎对象是老虎类型的
Tiger o2 = new Tiger();
//一个老虎对象是动物类型的
Animal o3 = new Tiger();//一个动物对象是老虎类型-------语义不同
//Tiger o4 = new Animal(); //编译错误
class Animal{	//动物
}
class Tiger extends Animal{	//老虎   
}
for(int i=0;i<bullets.length;i++){	//遍历所有子弹	
    Bullet b = bullets[i];	//获取每一个子弹    
    System.out.println(b.x+","+b.y);	//获取子弹的x和y坐标
}

2、方法的重写(override):重新写、覆盖

1)发生在父子类中,方法名相同,参数列表相同

2)重写方法被调用时,看对象的类型---------------------------这是规定

  3)遵循"两同两小一大"原则:------------------了解,一般都是一模一样

1)两同:        
    1.1)方法名相同        
    1.2)参数列表相同
2)两小:        
    2.1)派生类方法的返回值类型小于或等于超类方法的        
    2.2)派生类方法的抛出异常小于或等于超类方法的
3)一大:        
    3.1)派生类方法的访问权限大于或等于超类方法的

2021-6-11

1、重写与重载的区别:

  • 重写:发生在父子类中,方法名相同,参数列表相同

  • 重载:发生在同一个类中,方法名相同,参数列表不同

class Aoo{    
    void show(){  }
}
class Boo extends Aoo{	   
    void show(String name){  //此处发生了show方法的重载    
    }
}
Boo o = new Boo();
o.show();
o.show("zhangsan");

2、package 和 import:

package:

1)作用:避免类名的冲突
2)同一包中的类不能同名,
3)类的全称:包名.类名
4)建议:所有字母都小写

  import:

1)同包中的类可以直接访问,   不同包的类不能直接访问,若想访问:    
    1.1)先import 声明在访问类    
    1.2)类的全称

3、访问控制修饰符:-----------------访问控制的权限,保护数据的安全

常规操作:数据(成员变量)私有化(private),行为(方法)公开化(public)

  • public:公开的,任何类都能访问

  • private:私有的,只有本类才可以访问

  • protected:受保护的,本类、派生类、同包类都可以访问使用

  • 默认的:什么也不写,本类、同包类访问使用用 -------------------------java不建议默认权限

    • 1)类的访问权限只能是public或默认的

    • 2)类中成员的访问权限如上四种都可以

Card{	//银行卡
   private String cardId;	//卡号
   private String cardPwd;	//密码
   private double balance;	//账户余额
   
   public boolean payMoney(double money){	//支付金额
       if(balance >= money){
           balance -= money;
           return true;
       }else{
           return false;
       }
   }
   
   public boolean checkPwd(String pwd){	//检测密码是否输入正确
       if(pwd == cardPwd){
           return true;
       }else{
           return false;
       }
   }
}

4、final:最终的、不可改变的-------------单独应用几率低

  • 修饰变量:变量不能被改变

  • 修饰方法:方法不能被重写

  • 修饰类:类不能被继承

5、static:静态的

成员变量分为两种:
1)实例变量:没有 static 修饰,属于对象,存储在堆中,有几个对象就有几份,通过对象点来访问
2)静态变量:由 static 进行修饰,属于类,存储在方法区中,只有一份,通过类名点来访问

 1)静态变量:    
    1.1)由 static 修饰    
    1.2)属于类的,存储在方法区中,只有一份    
    1.3)常常通过类名点来访问    
    1.4)何时用:所有对象所共享的数据(图片、音频、视频等)
2)静态方法:    
    2.1)由 static 修饰    
    2.2)属于类的,存储在方法区中,只有一份   
    2.3)常常通过类名点来访问    
    2.4)静态方法中没有隐式 this 传递,没有 this 就意味着没有对象,所以静态方法中不能直接访问实例成员    
    2.5)何时用:方法的操作与对象无关
3)静态块:    
    3.1)由 static 修饰   
    3.2)属于类,在类被加载期间会自动执行,一个类只被加载一次,所以静态块也只被执行一次     3.3)何时用:加载/初始化静态资源(图片、音频、视频等)

 堆:new出来的对象栈:局部变量(包括方法的参数)方法区:class字节码文件(包括静态变量、所有方法)

 

2、静态方法:    
    package ooday06;    
//演示静态方法    
public class StaticDemo {		
    public static void main(String[] args){                   
    }    
}    
class Boo{        
    int a;  //实例变量        
    static int b;   //静态变量        
    public void show(){ //有个隐式的this传递           
        b = 25;            
        System.out.println(a);  //this.a            
        System.out.println(b);  //Boo.b        
    }        
    public static void test(){ 
        //没有隐式的this传递            
        /*静态方法中没有隐式的this传递           
        没有this就意味着没有对象            
        而实例变量a必须通过对象点来访问            
        */            
        System.out.println(new Boo().a);  //            
        System.out.println(b);  
        //Boo.b        
    }   
}    
class Coo{       
    int a;  //不适合做成静态的,因为和对象有关       
    public void show(){ //需要访问对象的数据a,所以不适合做成静态方法           
        a++;        
    }       
    public void test(int num1,int num2){ 
        //不需要访问对象数据,意味着与对象无关,更适合做成静态方法           
        int num = num1 + num2;            
        System.out.println(num);       
    }   
}

3、静态块:
    package ooday06;   
public class StaticDemo {        
    public static void main(String[] args) {            
        Doo o4 = new Doo();            
        Doo o5 = new Doo();       
    }   
}    
class Doo{        
    static {            
        System.out.println("静态块");       
    }        
    public Doo(){            
        System.out.println("构造方法");       
    }    
}结果:(静态方法执行一次,构造方法每次都执行)    静态块    构造方法    构造方法

2021-6-15

1、static final 常量:

1)必须声明同时初始化
2)常常通过类名点来访问,不能被改变(class.)
3)建议:所以字母都大写,多个单词用 _ 分隔
4)编译器在编译时会将常量直接替换为具体的值,效率高
5)何时用:数据永远不变,并且经常使用

package ooday06;

public class StaticFinalDemo {
    public static void main(String[] args) {
        System.out.println(Eoo.PI); //常常通过类名点来访问

        /*
        * 1)加载 Foo.class 到方法区中
        * 2)静态变量 num 一并存储到方法区中
        * 3)到方法区中获取 num 的值并输出
        * */
        System.out.println(Foo.num);

        //编译器在编译时会将常量直接替换为具体的值,相当于System.out.println(5);---效率高
        System.out.println(Foo.COUNT);
    }
}

class Eoo{
    public static final double PI = 3.14159;
    //public static final double NUM; //编译错误,常量必须声明同时初始化
}

class Foo{
    public static int num = 5;  //静态变量
    public static final int COUNT = 5;  //常量
}

2、抽象方法:

  • 设计规则:

  • 将派生类所共有的属性和行为,抽到超类中------------抽共性

  • 若派生类的行为都一样,设计为普通方法

    若派生类的行为不一样,设计为抽象方法

1)由 abstract 修饰
2)只有方法的定义,没有具体的实现(连{}都没有)

3、抽象类:

 1、由 abstract 修饰
2、包含抽象方法的类必须是抽象类
3、抽象类不能被实例化(不能 new 对象)
4、抽象类是需要被继承的,派生类
    4.1)重写所有抽象方法------常用
    4.2)也声明为抽象类--------不常用
5、抽象类的意义:
    5.1)封装共有的属性和行为----------代码复用
    5.2)为所有派生类提供统一的类型-----向上造型
    5.3)包含抽象方法,为所有派生类统一的入口(能点出来)
         派生类的具体实现不同,但入口是一致的
         达到强制必须重写的目的

FlyingObject 0; //正确
FlyingObjectp[] 0; //正确
new FlyingObject[3];  //正确,创建FlyingObject数组对象--------只要是数据类型,就能创建数组对象​
new FlyingObject(); //编译错误

1、问:抽象方法并没有达到让派生类复用的效果,为何还要存在?

答:不是的,抽象方法存在的意义在于,当向上造型通过超类的引用能点出step()来

2、问:既然抽象方法的意义仅仅在于造型后能点出来,那设计为普通方法也能点,为什么非要设计为抽象方法?

答:设计为普通方法,则派生类可以重写也可以不重写,而设计为抽象方法,可以强制派生类必须重写

---------抽象方法可以达到强制必须重写的目的

abstract class FlyingObject{    
    int width,height,x,y;    
    public abstract void step();
}
class Airplane extends FlyingObject{    
    @Override    
    public void step(){        
        System.out.println("神奇的事物");   
    }
}
class Bee extends FlyingObject{    
    @Override    
    public void step()
    {        
        System.out.printn("神奇的海豚");   
    }
}

2021-6-16

1、画对象

1)想画对象需要获取对象的图片,每个对象都得获取图片,意味着获取图片行为为共有的行为,所以设计在FlyingObject中,   每个对象获取图片的行为都是不一样的,所以设计为抽象方法   ---------在FlyingObject中设计getImage()获取对象图片   
2)准备对象的图片需要判断对象的状态,因为在不同的状态下获取的图片是不一样的,每个对象都有状态,意味着状态为共     有的属性,所以设计在FlyingObject中状态一般设计为常量,同时在设计变量 state 来表示当前状态   ---------在FlyingObject中设计LIVE,DEAD,REMOVE状态常量,state变量来表示当前状态,状态有了,还得去判断,每个对象都能判断状态,意味着判断状态行为为共有行为,所以设计在FlyingObject中,每个对象判断状态行为都是一样的,所以设计为普通方法------在FlyingObject中设计isLive(),isDead(),isRemove()判断状态   每个对象都得判断状态,意味着判断状态行为为共有状态,所以设计在FlyingObject中    
3)重写getImage()获取图片:    
    3.1)天空sky,直接返回sky图片即可    
    3.2)英雄机hero,返回heros[0]和heros[1]来回切换    
    3.3)子弹Bullet:        
        3.3.1)若活着的,返回bullet图片即可        
         3.3.2)若死亡的,直接删除(不返回图片)       
         3.3.3)若删除的,不反悔图片   
    3.4)小敌机Airplane:         
         3.4.1)若活着的,返回airs[0]图片即可         
         3.4.2)若死亡的,依次返回airs[1]和airs[4]的爆破图,4后删除不返回图片)    
    3.5)大敌机BigAirplane:         
         3.5.1)若活着的,返回bairs[0]图片即可         
         3.5.2)若死亡的,依次返回bairs[1]和bairs[4]的爆破图,4后删除(不返回图片)    
    3.6)小蜜蜂Bee:         
        3.6.1)若活着的,返回bees[0]图片即可         
         3.6.2)若死亡的,依次返回bees[1]和bees[4]的爆破图,4后删除(不返回图片)

 往窗口上画东西,需要三个数据: 1、对象的图片 2、对象的x坐标 3、对象的y坐标

2、成员内部类:

  • 类中套类,外面的称为外部类,里面的称之为内部类

  • 内部类通常只服务于外部类,对外不具备可见性

  • 内部类对象通常在外部类中创建

  • 内部类中可以直接访问外部类的成员(包括私有的)

    ----------内部类中有个隐式的引用指向了创建它的外部类对象-----外部类名.this

public class InnerClassDemo {
    public static void main(String[] args) {
        Mother m = new Mother();
        m.create();	
    }
}
class Mother{   //外部类
    private String name;
    void create(){
        Son s  = new Son();
        s.show();
    }
    class Son{  //内部类
        void show(){
            name = "三毛";
            System.out.println(name);
            System.out.println(Mother.this.name);
        }
    }
}

3、匿名内部类:------------------便于访问数据

  • 若想创建一个类(派生类)的对象,并且对象只被创建一次,此时该类不必命名,称为匿名内部类

  • 匿名内部类中不能修改外面变量的值,因为在此处系统默认该变量为 final 的

/* 匿名内部类演示*/
public class NsInnerClassDemo {
    public static void main(String[] args) {
        int num = 5;
        /**
         * 1)创建了Aoo的一个派生类,但是没有名字
         * 2)为该派生类创建了一个对象,名为 o1
         * 3)大括号中的为派生类的类体,
         * */
        Boo o1 = new Boo() {
            @Override
            void show() {
                System.out.println("this is show...");
                //num = 55;   //匿名内部类中不能修改外面变量的值,因为在此处该变量会默认为final
            }
        };

        o1.show();
    }
}

abstract class Boo{
    abstract void show();
}
**内部类命名:

外部类名 $	内部类名 .class

Mother  $	Son	  .class

**匿名内部类命名:

外部类名			  $ 	内部类名	.class

NsInnerClassDemo	 $     1		 .class

Shoot射击游戏第八天

  • 敌人入场:-------------------------自动发生

    • 敌人对象是由窗口产生的,所以将创建敌人方法设计在窗口World类中

      • 在World中设计 nextOne() 方法生成敌人对象

      • 敌人入场为定时发生的,所以在run中调用 enterAction() 实现敌人入场

        • 在enterAction()中:

        • 每400毫秒,获取敌人对象obj,enemies扩容,将obj装到最后一个元素上

        • ----------------------在run中调用enterAction()后,需调用repaint()来重画

  • 子弹入场:-------------------------自动发生

    • 子弹对象是由英雄机发射出来的,所以将创建子弹的方法设计在英雄Hero类中

      • 子弹是由英雄机发射出来的,所以在Hero类中设计 shoot() 方法生成子弹对象

      • 子弹入场为定时发生的,所以在run中调用shootAction() 实现子弹入场

        • 在shootAction() 中:

        • 每300毫秒,获取子弹数组bs,bullets扩容,数组的追加

  • 飞行物移动:-----------------------自动发生

    • 飞行物移动为所有对象共有行为,所以将飞行物移方法设计在超类FlyingObject类中

      • 飞行物移动为所以派生类共有的行为,所以在FlyingObject中设计抽象 step() 移动,派生类重写

      • 飞行物移动为定时发生的,所以在 run 中调 stepAction() 实现飞行物移动

        • 在stepAction() 中:

        • 天空动,遍历敌人动,遍历子弹动

  • 英雄机移动:-----------------------自动发生

    • 英雄机移动为英雄机特有的行为,所以将英雄机移动方法设计在英雄机Hero类中

      • 英雄机移动为英雄机的行为所以在Hero类中设计 moveTo() 实现英雄机的移动

      • 英雄机移动为事件触发的,所以在监听器中中重写mouseMoved()鼠标移动事件

  • 删除越界的敌人和子弹

    • 在 FlyingObject中设计isOutOfBounds检测敌人是否越界

    • 在Bullet中重写isOutOfBounds检测子弹是否越界

  • 删除越界的敌人和子弹为定时发生的,所以在run中调用outOfBoundsAction()删除越界敌人和子弹

    • 在outOfBoundsAction()中:

    • 遍历敌人/子弹数组,判断若越界了,将越界敌人/子弹替换为最后一个元素,在将数组缩容

  • 子弹与敌人想碰撞,若击中了

    • 子弹消失,敌人先爆破在消失

    • 若击中的是小敌机,则玩家得1分

      若击中的是大敌机,则玩家得3分

      若击中的是小蜜蜂,则英雄机得奖励(1条命或40火力值)

      若击中的是大黄蜂,则英雄机得奖励

    • 设计EnemyScore得分接口:Airplane和BigAirplane实现得分接口

    • 设计EnemyAward奖励接口:

  • 子弹与敌人的碰撞

    • 在FlyingObject中设计isHit()碰撞检测,goDead()飞行物去死

      • 在Hero设计addLife()增命,addFire()增火力

    • 子弹与敌人的碰撞为定时发生的,所以在run中调用bulletBangAction() 实现子弹与敌人的碰撞

class Bullet{ 
    //子弹撞敌人
	public boolean isHit(FlyingObject other){
        //this:子弹	other:敌人

    }
}
class FlyingObject{ 
    //敌人撞子弹
    public boolean isHit(Bullet other){
        this:敌人
        other:子弹
    }
    //敌人撞英雄机
    public boolean isHit(Hero other){
    	this:敌人
        other:英雄
    }
}

class FlyingObject{
    public boolean isHit(? other){ //?为FlyingObject---超类 类型
    }
}

enemies[i].isHit(bullet[i]) //敌人撞子弹 this为敌人 other为子弹

enemies[i].isHit(Hero)	//敌人撞英雄机   this为英雄	other为子弹

接口、超类 

? 处设计成什么类型:
    既能接受子弹对象
    也能接受英雄机对象
 使用超类:FlyingObject 类型

检测是否碰撞:

  • 英雄机与敌人的碰撞

    • 借用FlyingObject的isHit() 检测碰撞,goDead() 飞行物死亡

      • 在Hero中设计subtractLife()减命,clearFire()清空火力值

    • 英雄机与敌人相撞是定时发生的,所以在run中调用heroBangAction() 实现英雄机与敌人碰撞

      • 在run中设计 heroBangAction() 方法实现英雄和敌人的碰撞

  • 检测游戏结束

    • 借用Hero的getLife()获取命数

    • 检测游戏结束为定时发生的,所以在run中调用checkGameOverAction() 实现检测游戏结束

      • 在checkGameOverAction() 中:

        • 判断若英雄机的命数<=0,表示游戏结束

  • 画状态

    • 在World类中设计START、RUNNING、PAUSE、GAME_OVER状态量、state变量

      在Images类中设计start,pause,gameover状态图片,static块中赋值

      在World的paint()中,设计在不同的状态下画不同的图片

    • 在run中那一堆 action设计为仅在运行状态下执行

      将英雄机随着鼠标移动设计为仅在运行状态下执行

    • 重写mouseClicked()鼠标点击事件:

      • 启动变运行,游戏结束时清理现场再变启动

    • 重写mouseExited()鼠标移出事件:

      • 运行状态变为暂停状态

    • 重写mouseEntered()鼠标移入事件:

      • 暂停状态变为运行状态

  • 接口的好处?

    • 达到所以实现该接口的都能执行,提供复用性

  • 行为的多态、对象的多态?

    • getScore() 和 getAwardType() 体现了行为的多态,不同对象有不同的实现

    • 被撞敌机为多态的,它作为FlyingObject时只能操作FlyingObject中的,作为接口类型时,只能操作接口中的

  • 向上造型的好处?

    • 将所以敌人封装到FlyingObject数组中,来提高复用性

  • 为什么要强制类型转换?

    • 若想访问的东西在超类中有,则不需要强转;若想访问的东西在超类中没有,则必须强转

  • 为什么要 instranceof 判断?

    • 为了避免ClassCastException 类型转换异常

定时器:

timer.schedule(7,10,10);
//第一个参数:TimeTask类型
//第一个10:从程序启动开始到第一次触发的时间间隔(long类型)
//第二个10:从第一次触发到第二次触发的时间间隔(long类型)
		   从第二次触发到第三次触发的时间间隔

做功能的套路:

  • 先写行为(方法):

    • 若为某个派生类所特有的行为,就将方法设计在特定的类中

    • 若为所有派生类所共有的行为,就将方法设计在超类中

  • 窗口去调用

    • 若为定时发生的,就在定时器中调用

    • 若为事件触发的,就在监听器中调用

如何调错:

  • 编译错误:

  • 异常:

  • 程序的运行结果与你预期的结果不同:

    调错方法

    • 锁定错误方法:将方法注释掉,挨个放开,放开哪个方法出错,说明错误位置就是那个方法

    • 打桩:System.out.println(数据)

2020-6-18

1、接口:

  • 是一种数据类型(引用类型)

  • 由 interface 定义

  • 只能包含常量和抽象方法

  • 默认成员权限为------public

  • 接口不能被实例化

  • 接口是需要被实现/继承的,实现/派生类类:

    • 必须重写接口中的所有抽象方法

  • 一个类可以实现多个接口,用逗号分隔,若又继承又实现时,应先继承后实现

  • 接口可以继承接口

  • 何时用:

//接口的演示
public class InterfaceDemo {
    public static void main(String[] args) {
		
    }
}
interface Inter{
    public static final int NUM = 5;
    public abstract void show();

    int COUNT = 5;  //默认public static final
    void test();    //默认public abstract

    //int NUMBER; //编译错误,常量必须声明同时初始化
}

class Aoo implements Inter{
    @Override
    public void show() {    //重写接口中的抽象方法,必须加public
        
    }

    @Override
    public void test() {

    }
}
接口继承接口:
    interface Inter5{
    void show();
    }
    interface Inter6 extends Inter5{
        void test();
    }
    class Boo implements Inter6{

        @Override
        public void show() {

        }

        @Override
        public void test() {

        }
    }

设计规则:

  1. 将派生类所共有的属性和行为,抽到超类中

  2. 若派生类的行为都一样,设计为普通方法

  3. 若派生类的行为都不一样,设计为抽象方法

  4. 将部分派生类所共有的属性和行为,抽到接口中

    接口是对继承的单根性的扩展---------------------实现多继承

2、多态:------------------多种形态

(1)意义:

  • 行为的多态:cut()、step()、getImage()...

    • 同一类型引用在指向不同的对象时,有不同的实现------所有抽象方法都是多态的

  • 对象的多态:我、水 ....

    • 同一对象在被造型为不同的类型时,有不同的功能--------所有对象都是多态的

(2)向上造型:

  • 超类的引用指向派生类的对象

  • 能造型成为的类型有:超类+所实现的接口

  • 能点出来什么,看引用的类型

(3)强制类型转换,成功的条件只有如下条件:

  • 引用所指向的对象,就是该类型

  • 引用所指向的对象,实现了该接口或继承了该类

(4)强转时若不符合如上条件,则发生ClassCastException类型转换异常

  • 建议:在强转之前先通过 instanceof 来判断引用指向的对象是否是该类型

public class MultiTypeDemo{
    public static void main(String[] args) {
        Aoo o = new Boo();  //向上造型
        Boo o1 = (Boo)o;    //强转,引用o所指向的对象,就是Boo类型
        Inter o2 = (Inter)o;  //引用o所指向的对象,实现了Inter接口
        //Coo o3 = (Coo)o;    //运行时会发生ClassCastException类型转换异常

        //做判断
        if (o instanceof Coo){
            Coo o4 = (Coo)o;    //强转失败
        }else{
            System.out.println("o不是Coo类型");
        }

        System.out.println(o instanceof Boo);   //true
        System.out.println(o instanceof Inter); //true
        System.out.println(o instanceof Coo);   //false

    }
}

多态的演示

public class Test {
    public static void main(String[] args) {
        show(new Cat());  // 以 Cat 对象调用 show 方法
        show(new Dog());  // 以 Dog 对象调用 show 方法

        Animal a = new Cat();  // 向上转型  
        a.eat();               // 调用的是 Cat 的 eat
        Cat c = (Cat)a;        // 向下转型
        c.work();        // 调用的是 Cat 的 work
    }

    public static void show(Animal a)  {
        a.eat();
        // 类型判断
        if (a instanceof Cat)  {  // 猫做的事情
            Cat c = (Cat)a;
            c.work();
        } else if (a instanceof Dog) { // 狗做的事情
            Dog c = (Dog)a;
            c.work();
        }
    }
}

abstract class Animal {
    abstract void eat();
}

class Cat extends Animal {
    public void eat() {
        System.out.println("吃鱼");
    }
    public void work() {
        System.out.println("抓老鼠");
    }
}

class Dog extends Animal {
    public void eat() {
        System.out.println("吃骨头");
    }
    public void work() {
        System.out.println("看家");
    }
}

2021-6-21

get/set的用法:

内存管理:由JVM来管理

堆:

  • 存储 new 出来的对象(包括实例变量)

  • 垃圾:没有任何引用所指向的对象

    垃圾回收器 (GC) 不定时到内存中清扫垃圾,回收过程是透明的(看不到的),

    并非一看到垃圾就立即回收,通过调用System.gc() 建议JVM尽快调度GC来回收

  • 实例变量的生命周期:

    当创建对象时存储在堆中,对象被回收时一并被回收

  • 内存泄漏:不在使用的对象没有被及时的回收,严重的泄漏会导致系统的崩溃

    建议:不再使用的对象应及时将引用设置为 null

栈:

  • 存储的是 正在调用的方法中的所有局部变量(包括方法的参数)

  • 调用方法时:会在栈中为该方法分配一块对应的栈帧,栈帧中存储局部变量(包括参数),

    方法调用结束时,栈帧自动被清除,局部变量一并被消除

  • 局部变量的生命周期:调用方法时存储在栈中,方法调用结束时与栈帧一并被清除

 

方法区:

  • 存储的是 .class 字节码文件(包括静态变量、所有方法)

  • 方法只有一份,通过this 来区分具体的方法对象

实例变量和局部变量:

  • 实例变量:

    • 类中,方法外

    • 创建对象时存储在堆中,对象被回收时一并被回收

    • 有默认值

  • 局部变量:

    • 方法中

    • 调用方法时存储在栈中,方法调用结束时与栈帧一并被清除

    • 没有默认值

面向对象总结

面向对象三大特征:

  • 封装:

    • 类:封装的是 对象的属性和行为

    • 方法:封装的是 具体的业务逻辑实现

    • 访问控制修饰符:封装的是 具体的访问权限

  • 继承:

    • 作用:实现 代码复用

    • 超类:所有派生类所共有的属性和行为

      接口:部分派生类所共有的属性和行为

      派生类:派生类所特有的属性和行为

    • 单一继承、多接口实现,传递性

  • 多态:

    • 行为多态:所有抽象方法都是多态的(通过方法的重写来实现)

      对象多态:所有对象都是多态的(通过向上造型来实现)

    • 向上造型、强制类型转化、instanceof 判断

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值