>>>子类对象的初始化问题
在创建子类的时候 会先调用父类的无参构造
class Person{
}
class Teacher extends Person{
//在创建子类的时候 如果这里什么也不写会 默认的给你加上 Teacher(){super()}
}
如果父类里面写了构造函数
class Person{
Person(String name){}
}
class Teacher extends Person{
//如果现在什么也不写会报错的 因为这里默认的调用了 父类的无参构造 而在父类中 有参构造 把无参构造覆盖了 所以就找不到super();父类的无参了
}
如果想调用父类的有参构造 可以
class Teacher extends Person{
Teacher(){
super("aa");
}
}
为什么父类的构造子类不能继承(复写) 因为 构造函数的定义是 方法名和类名相同 而明显的是:子类的名字不能和父类的名字相同 所以 构造方法不能继承
>>>>this 和super
this表示类的当前对象的引用 super 表示类的父类的对象引用 调用父类的构造用super() 调用父类的变量用super.name 调用方法用super.fun();
在子类的构造方法中 只能出现一个词 要不this 要不super 他们不能同时出现 并且在创建子类的时候 必须有一个构造方法调用父类的构造方法 必须的
>>重载和重写
重载是方法名相同 参数列表和个数不同与返回值无关
重写 只能出现在方法父类和子类之间 并且子类的方法名和返回值类型必须和父类的一模一样 并且子类不能缩小父类的访问权限 但是可以扩大父类的访问权限
子类覆盖父类的方法时, 不能比父类的访问权限更弱.
子类覆盖父类的方法时, 不能比父类抛出更多的异常
因为父类有的功能子类都要有, 所以子类只能比父类更强, 不能比父类更弱.
>>object类的三个方法
>1.finalize()
此方法在对象销毁之前执行 垂死前的挣扎 有垃圾回收器自动调用 并且这个是按量来存储的 不会马上执行 只有当到一定地步的时候才执行
equals() 用==比较的是内存中的地址 用equals默认的比较也是内存中的地址 最好复写object中的equals()方法
如果object里面的equals方法不好 最好自己写一个equals 方法 这样就能用equals比较连个对象的属性了
以后写类时写equals方法, 比较对象时调用equals方法
public boolean equals(Object obj){
if(this == obj) // 判断如果地址相同, 直接返回true, 地址相同属性肯定相同
return true;
if(obj == null) // 判断如果传入对象为null, 直接返回false, 因为可以执行这个方法, 那么调用equals的对象肯定不是null
return false;
if(!(obj instanceof Person)) // 判断obj如果不是Person类型, 直接返回false
return false;
Person p = (Person)obj; // 由于形参定义时Object类型, 不能直接访问Person类的属性, 所以强转
if(!this.name.equals(p.name)) // 判断名字是否不同, 如果不同, 返回false
return false;
if(this.age != p.age) // 判断年龄是否不同, 如果不同, 返回false
return false;
return true; // 如果名字和年龄都一样, 那么我们就认为这两个对象相同, 返回true
}
注解 @override
为了检查覆盖是否成功, 我们在覆盖父类的方法时可以使用 @Override 来测试.
>>>封装的第三大特性 多态
1.以不变应万变
定义一个方法的时候, 将形参定义为父类类型, 以后所有子类对象都可以传入.
根据传入的实参类型不同, 运行的结果也就不同.
2.向后兼容
将形参定义为父类对象, 而不是具体制定某一子类.
这样以后如果新定义一个类, 只要继承于指定的父类就可以传入.
先写的代码可以调用后写的代码.
>>>>>>>>>>>>>>>>以后写方法时, 形参尽量定义成父类类型, 这样可以让更多对象传入.
>抽象类
当我们定义的多个类有相同的方法声明时, 就可以抽象到父类中定义.
这时别人看到我们的父类的抽象方法, 就知道所有子类中都会有这个方法.
抽象类中的抽象方法 在子类中必须实现 抽象类就是用来被继承的
>>final
final 的类不能被继承 称为太监类 不能派生新类
final的方法不能被 重写 是最终的方法
final的变量 被称为常量 如果定义的时候没有赋值 就只能赋值一次 以后再也不能修改 了
基本类型的变量 是在栈区中的值不能被修改 而引用数据类型 是栈区中的地址不能修改 但是在堆区里面的内容可以修改 不要搞混啊
使用public static final DAXIE修饰的常量是全局常量, 一般全部大写.
>>>>>三种设计模式
单例 教我们基础班的只有一个老师 只能new出来一个老师的实例
class Teacher {
final private static Teacher teacher = new Teacher(); // 2.在类内部创建一个对象, 定义一个该类类型的成员变量引用这个对象.
private Teacher(){ // 1.私有化构造函数, 类外部不能创建对象.
}
public static Teacher getInstance(){ // 3.定义一个公有的方法, 让别人可以获取到这个唯一的对象.
return teacher;
}
}
>>组合设计模式
在定义一个类的时候, 需要使用另一个类的方法, 就可以使用组合设计模式.
实现步骤
a).先定义一个需要类的类型的成员变量
b).通过构造函数将一个这个类型的对象组合进来
c).在需要使用这个类的方法时, 通过属性调用方法
class ComboPattern {
public static void main(String[] args){
/*
Person p = new Person(new CreditCard());
p.shopping();
*/
Student s = new Student(new CreditCard());
s.shopping();
}
}
class Person { // Person类要使用Card类的方法, 所以用到组合
private Card card; // 先定义一个Card类型的成员变量
public Person(Card card){ // 通过构造函数将一个Card对象组合进来
this.card = card;
}
public void shopping(){
card.spend(); // 在需要使用Card类的方法时, 使用这个属性调用方法
System.out.println("买了一台IPHONE5");
}
public Card getCard(){
return card;
}
public void setCard(Card card){
this.card = card;
}
}
class Student extends Person { // 子类继承父类, 一定要调用父类的构造函数
public Student(Card card){
super(card);
}
}
class Card {
public void spend(){
System.out.println("刷卡消费, 一不小心花了100元.");
}
}
class CreditCard extends Card {
public void spend(){
System.out.println("刷卡消费, 先欠着.");
}
}
>>模板设计模式
在做一件事的时候, 需要先定义一个模板, 以后执行时按照模板定义的步骤去做.
实现方式
a)先定义一个抽象类作为模板
b)在类中定义抽象方法, 每一个方法是一个步骤
c)再定义一个供外界调用的主方法, 这个方法中调用抽象方法完成每一个步骤.
这个主方法使用final修饰, 不能修改.
class TemplatePattern {
public static void main(String[] args){
// new MyLeave().run();
// 想请假: 写一个子类, 创建对象, 调用run()方法.
new LeaveTemplate(){ // 匿名内部类, 先定指定类的子类, 然后根据这个类创建对象.
public void apply(){
System.out.println("我要请婚嫁, 请一个月.");
}
public void approve(){
System.out.println("找副总审批.");
}
public void leave(){
System.out.println("我要去渡蜜月.");
}
}.run();
}
}
abstract class LeaveTemplate {
abstract public void apply(); // 提交申请
abstract public void approve(); // 经理审批
abstract public void leave(); // 离开
final public void run(){
apply();
approve();
leave();
}
}
class MyLeave extends LeaveTemplate {
public void apply(){
System.out.println("我要请病假, 休息三天");
}
public void approve(){
System.out.println("找部门经理审批");
}
public void leave(){
System.out.println("去医院看病");
}
}
最重要的一个题
有一个农场, 农场里有两头牛, 牛每三年生两头小牛. 牛的寿命是10年.
问: 20年后农场中有多少牛.
写程序设计一个方法, 计算N年后农场有多少头牛.
main(){
创建2头牛, 放入farm
循环20次. 每次让farm中的所有牛长大1岁
}
class Cattle{
int age
static Cattle[] farm = new Cattle[1000];
void growUp(){
判断年龄, 如果是3的倍数
就创建新牛, 添到farm中
判断年龄, 如果等于10
就从farm中将自己移出
}
}
1 2
2 2
3 4
4 4
5 4
6 8
7 8
8 8
9 16
10 14
11 14
12 28
13 26
14 26
15 52
16 48
17 48
18 96
19 88
20 88