1.现实生活中是由很多很多对象组成的,基于对象抽出类
2.对象:软件中真实存在的单个个体/东西
类:类别/类型,代表一类个体
3.类是对象的模子,对象是类的具体的实例
4.类可以包含:
对象的属性/特征--------成员变量
对象的行为/动作--------方法
5.一个类可以创建多个对象
发生在同一类中,方法名相同,参数列表不同
潜艇游戏需求: 1.所参与的角色: 窗口:宽(?),高(479) 1)战舰Battleship 属性:宽(66),高(26),x坐标(270),y坐标(124),移动速度(20),命数(5) 行为:移动move() 2)侦察潜艇ObserveSubmarine 属性:宽(63),高(19),x坐标(-width),y坐标(150到(窗口高-潜艇高)之内的随机数),移动速度(1~3) 行为:移动move() 3)鱼雷潜艇TorpedoSubmarine 属性:宽(64),高(20),x坐标(-width),y坐标(150到(窗口高-潜艇高)之内的随机数),移动速度(1~3) 行为:移动move() 4)水雷潜艇MineSubmarine 属性:宽(63),高(19),x坐标(-width),y坐标(150到(窗口高-潜艇高)之内的随机数),移动速度(1~3) 行为:移动move() 5)水雷Mine 属性:宽(11),高(11),x坐标(写活),y坐标(写活),移动速度(1) 行为:移动move() 6)深水炸弹Bomb 属性:宽(9),高(12),x坐标(写活),y坐标(写活),移动速度(2) 行为: 2.角色间的关系: 1_1)战舰发射深水炸弹; 1_2)深水炸弹可以打潜艇(侦察潜艇、鱼雷潜艇、水雷潜艇),若打中: ① 潜艇消失,深水炸弹消失; ② 得东西: 打掉侦察潜艇,玩家得10分; 打掉鱼雷潜艇,玩家得40分; 打掉水雷潜艇,战舰得1条命. 2_1)水雷潜艇可以发射水雷; 2_2)水雷可以击打战舰,若打中: ① 水雷消失; ② 战舰减一条命(命数为0时游戏结束).
--方法名与类名相同,且没有返回值类型(void都没有)
--在创建(new)对象时自动被调用
--若不写构造方法,编译器默认提供一个无参构造方法,若写构造方法,编译器不会自动生成构造方法
--构造方法可以重载
1. 只能用在方法中,方法中访问成员变量之前默认有个this.
2.this的用法:
1)this.成员变量名---------------访问成员变量
成员变量与局部变量同名时,若想访问成员变量则this不能省略
2)this.方法名----------调用方法(了解)
3)this()-------------------调用构造方法(了解)
null表示空,没有指向任何对象,若引用的值为null,则该引用不能进行任何点操作了,否则会发生NullPointerException空指针异常
Bomb[] bs = new Bomb[3]; bs[0] = new Bomb(100,200); //1)给元素赋值需要去new个对象 bs[1] = new Bomb(200,300); bs[2] = new Bomb(220,330); //2)若想访问对象的数据,需要通过数组元素去打点 bs[0].x = 111; //给第1个炸弹的x修改为111 System.out.println(bs[1].width); //输出第2个炸弹的宽 bs[2].move(); //第3个炸弹移动
1.内存管理:由JVM管理
1)堆内存:new的对象(还有实例变量)
2)栈内存: 局部变量(包括方法的参数)
- 作用:代码复用
- 通过extends来实现继承
- 超类/父类:共有的属性和行为
派生类/子类:特有的属性和行为
- 派生类既能访问自己的,也能访问超类的,但超类不能访问派生类的
- 一个超类可以有多个派生类
一个派生类只能有一个超类-----------单一继承
- 具有传递性
- java规定:构造派生类之前必须先构造超类
- 派生类的构造方法中若没有调用超类的构造方法,则默认super()调用超类的无参构造方法
- 派生类的构造方法中若自己调用了超类的构造方法,则不再默认提供
super()调用超类构造方法,必须位于派生类构造方法的第一行
super的用法:
- super.成员变量名----------------------访问超类的成员变量(了解)
- super.方法名()---------------------------调用超类的方法----------明天讲
- super()-------------------------------------调用超类的构造方法
- 超类型的引用指向了派生类的对象
- 能点出来什么,看引用的类型-----------这是规定,记住就OK了
1. 继承意味着代码虽然我没有写,但也属于我,只是没有写在一起而已
2. 泛化:将共有的抽出来的过程,泛化是设计层面的概念,从代码实现层面来说咱们就是继承,泛化就是继承
3. 继承要符合is a(是一个)的关系
1.发生在父子类中,方法名相同,参数列表相同
2.重写方法被调用时,看对象的类型
1.重写(override)-------父子类中,方法名相同,参数列表相同
多态中,重写的方法看对象
一般用于在派生类中修改超类的方法
2.重载(overload)------同类中,方法名相同,参数列表不同
是完全不同的方法,只是方法名相同而已
- package:声明包
- 作用:避免类的命名冲突
- 同包中的类不能同名,不同包中的类可以同名
- 类的全称:包名.类名,包名常常有层次结构
- 建议:包名所有字母都小写> 说明:package声明包必须位于第一行
- import:导入类
- 同包中的类可以直接访问,不同包的类不能直接访问,若想访问:
- 先import导入类,再访问类----------建议
- 类的全称-----------------------------------太繁琐,不建议> 说明:import导入类必须位于声明包的下一行
封装的意义:隐藏一些东西,暴露一些东西,来保护数据的安全
public:公开的,所有类
protected:受保护的 当前类,派生类,同包类
默认的:本类,同包类
private:私有的 本类
1. 类的访问权限只能是public或默认的
2. 类中成员的访问权限如上四种都可以
静态变量:
- 由static修饰
- 属于类,存储在方法区中,只有一份
- 常常通过类名点来访问
- 何时用:所有对象所共享的数据(图片、音频、视频等)
- 静态方法:
- 由static修饰
- 属于类,存储在方法区中,只有一份
- 常常通过类名点来访问
- 静态方法没有隐式this传递,所以不能直接访问实例成员
- 何时用:方法的操作与对象无关
- 静态块:
- 由static修饰
- 属于类,在类被加载期间自动执行,一个类只被加载一次,所以静态块也只执行一次
- 何时用:初始化/加载静态资源(图片、音频、视频等)
补充:
1. 成员变量分两种:
- 实例变量:没有static修饰,属于对象的,存储在堆中,
有几个对象就有几份,通过引用打点来访问
- 静态变量:有static修饰,属于类的,存储在方法区中,
只有一份,通过类名打点来访问
2. 内存管理:由JVM来管理的
- 堆:new出来的对象(包括实例变量)
- 栈:局部变量(包括方法的参数)
- 方法区:.class字节码文件(包括静态变量、所有方法)3. 在构造方法中给实例变量做初始化
在静态块中给静态变量做初始化
4.两同两小一大
1)两同:方法名相同,参数列表相同
2)两小:
派生类方法的返回值类型必须小于或等于超类方法的
----是void或基本数据类型时,必须相等
----引用类型时,小于或等于
派生类方法抛出的异常必须小于或等于超类方法的
3)一大:
派生类方法的访问权限必须大于或等于超类方法的
1.修饰变量:变量不能被改变
2.修饰方法:方法不能被重写
3.修饰类:类不能被继承
1.必须声明同时初始化
2.通过类名点来访问,不能被改变
3.建议:常量名所有字母都大写,多个单词用_分隔
4.编译器在编译时会将常量直接替换为具体的值,效率高
5.何时用:数据永远不变,并且经常使用
1.由abstract修饰
2.只有方法的定义,没有具体的实现(连{}都没有)
1.由abstract修饰
2.包含抽象方法的类必须是抽象类
3.抽象类不能被实例化(new对象)
4.抽象类是需要被继承的,派生类:
1)重写所有抽象方法-------变不完整为完整
2)也声明为抽象类----------一般不这么做
1)封装共有的属性和行为----代码复用
2)为所有派生类提供统一的类型------向上造型----代码复用
3)可以包含抽象方法,为所有派生类提供统一的入口(能点出来)
----派生类的行为不同,但入口是一致的,同时相当于定义了一个标准
补充:
设计规则:
---符合既是也是原则时,应使用接口
将所有派生类所共有的属性和行为,抽到超类中-------------抽共性
派生类的行为都一样,则设计为普通方法
派生类的行为不一样,则设计为抽象方法
将部分派生类共有的属性和行为,抽到接口中
接口是对继承的单根性的扩展-----------实现多继承
抽象方法/抽象类的疑问:
抽象方法的存在意义是什么?
保证当发生向上造型时,通过超类型的引用能点出来那个方法既然意义只在于能点出来,那为什么不设计为普通方法?
若设计为普通方法,则派生类可以重写也可以不重写,而设计为抽象方法,可以强制派生类必须重写------做了个标准,强制必须重写
class Aoo{ //外部类 class Boo{ //内部类 } }
--类中套类,外面的称为外部类,里面的称为内部类
--内部类通常只服务于外部类,对外不具备可见性
--内部类对象只能在外部类创建
--内部类可以直接访问外部类的成员(包括私有的),在内部类中有个隐式的引用指向了创建它的外部类对象---外部类名.this
--若想创建一个类(派生类)的对象,并且对象只创建一个,此时该类不必命名,称为匿名内部类
--匿名内部类中不能修改外面变量的值,因为在此处默认变量为final的
public class AnonInnerClassDemo{ public static void main(String[] args){ //1)创建了Aoo的一个派生类,但没有名字 //2)为该派生类创建了一个对象,名为o1 //3)大括号中的为派生类的类体 Aoo o1 = new Aoo(){ }; //由于大括号为派生类的类体,所以抽象方法要重写 Boo o2 = new Boo{ void show(){ System.out.println( "showshow" ); } }; o2.show(); } } abstract class Boo{ abstract void show(); } abstract class Aoo{ }
1.隐式对象:
--this:当前对象
--super:当前对象的超类对象
--外部类名.this:当前对象的外部类对象
2.必须记住的,API中会用的:
--外部类名.this-------------指代当前对象的外部类对象
--匿名内部类不能修改外面变量的值,因为在此处默认变量为final的
3.面试题:
--问:内部类独立生成.class字节码文件吗?
--答:是
4.做功能的套路:
1)先写行为/方法:
--若为某对象所特有的行为,就将方法设计在特定的类中
--若为所有对象所共有的行为,就将方法设计在超类中
2)窗口调用:
--若为定时发生的,就在定时器中调用
--若为事件触发的,就在侦听器中调用
5.调错方式
--打桩:System.out.println(数据);
1.语法:
1)是一种引用数据类型
2)由interface来定义(没有class关键字)
3)只能包含常量和抽象方法(默认权限是public且默认常量和抽象方法,可以省略修饰符)
4)接口不能被实例化
5)接口是需要被实现,实现类:必须重写所有抽象方法
--重写接口的方法时,访问权限必须设计为public的
6)一个类可以实现多个接口
--若又继承又实现时,应先继承后实现
7)接口可以继承接口(extends)
2.何时用:
接口的意义:
--封装部分派生类共有的属性和行为,实现多继承
--制定了一个标准,一种规范
3.用它的好处---------------第八天内容
1.类和类-----------------继承extends
接口和接口-----------继承extends
类和接口--------------实现implements
2.接口可以向上造型
1.表现:
1.同一个对象被造型为不同的类型时,有不同的功能
--对象的多态:
我(学生、儿子、哥哥)、你(老师、母亲)、水(气态、液态、固态)......-----------所有对象都是多态的
2.同一个类型的引用指向不同的对象时,有不同的实现
--行为的多态:move(),getImage(),getScore().....------------所有抽象方法都是多态的
2.向上造型/自动类型转换------代码复用
--超类的引用指向派生类的对象
--能点出来什么看引用
--能造型成为的数据类型有:超类+所实现的接口
3.强制类型转换,成功的条件只有如下两种:
--引用所指向的对象,就是该类型
--引用所指向的对象,实现了该接口或继承了该类
PS:强转时若不符合如上条件,则发生ClassCastException类型转换异常
1.建议:在强转之前先通过instanceof来判断引用的对象是否是该类型
2.何时需要强转?
想访问的属性/行为在超类中没有,必须强转;强转之前先instanceof判断
1.堆:
--存储new出来的对象(包括实例变量)
--垃圾:没有任何引用所指向的对象
垃圾回收器(GC)不定时到内存中清扫垃圾,回收的过程中透明的(看不到的),不一定一发现垃圾就立刻回收,通过调用System.gc()建议虚拟机尽快调度GC来回收
--实例变量的生命周期:
创建对象时存储在堆中,对象被回收时一并被回收
--内存泄漏:不再使用的对象没有被及时的回收,严重的泄漏会导致系统的崩溃
建议:不再使用对象应及时把引用设置为null
2.栈:
--存储正在调用的方法中的局部变量(包括方法的参数)
--调用方法时,会为该方法在栈中分配一块对应的栈帧,栈帧中存储局部变量(包括方法的参数),方法调用结束时,栈帧被自动清除,局部变量一并被清除
--局部变量的生命周期:
调用方法时存储在栈中,方法调用结束时,栈帧被自动清除,局部变量一并被清除
3.方法区:
--存储.class字节码文件(包括静态变量,所有方法)
--方法只有一份,
1.封装:
1)类:封装对象的属性和行为
2)方法:封装的是具体的业务逻辑实现
3)访问控制修饰符:封装的是具体的访问权限
2.继承:
1)作用:代码复用
2)超类:所有派生类所共有的属性和行为
接口:部分派生类所共有的属性和行为
派生/实现类:派生类所特有的属性和行为
3)单一继承、多接口实现,具有传递性
3.多态:
1)行为多态:所有抽象方法都是多态的(通过重写来表现)
对象多态:所有的对象都是多态的(通过向上造型来表现)
2)重写、向上造型、强制类型转换、instanceof判断
1.实例变量和局部变量的区别:
实例变量:
--写在类中,方法外
--创建对象时存储在堆中,对象被回收时一并被回收
--有默认值
局部变量:
--写在方法中
--调用方法时存储在栈中,方法调用结束时,栈帧被自动清除,局部变量一并被清除
--没有默认值
2.面试题:
问:java是值传递,还是引用传递?
答:java中只有值传递,基本数据类型传递的是具体的数,引用数据类型传递的是地址值
3.文档注释
文档注释是功能性的注释,只在三个地方使用,分别是类上,方法上,常量上.
1)在类上使用时,用来说明当前类的设计目的和整体功能介绍
/** 作者必须写,建议用英文名 @author XKB see表示参考的哪个类 @see java.lang.String */2)在常量上使用时,用来说明该常量用于哪个方法
/** * sayGoodbye方法中使用的问候语 */ public static final String INFO = "再见!";3)在方法上使用时,用来说明参数和返回值(输入/**再按回车会自动生成注解@)
/** * 为指定的用户添加问候语 * @param name 指定用户的名字 * @return 含有问候语的字符串 */ public String sayGoodbye( String name ){ return INFO + name; }4.get/set