1、两个类之间只要产生了关系,就可以考虑继承,继承是多态的前提
public static void main(String[] args) {
Zi z = new Zi();
z.show(); //输出20--13--10--11--14--15--15--15--18--20
}
}
class Fu {
int num = 10;
int a = 100;
public void methodFu(){
System.out.println("我是父类成员方法");
}
}
class Zi extends Fu {
// 如果子父类中, 出现了重名的成员变量, 在使用的时候, 用的子类的成员变量
int num = 20;
public void methodZi(){
System.out.println("我是子类成员方法");
}
public void show(){
int num = 30;
System.out.println(num);
System.out.println(this.num);
System.out.println(super.num);
System.out.println(super.a);
System.out.println(this.a);
this.methodZi();
super.methodFu();
this.methodFu();
}
2、构造方法不能被子类集成使用,原因:构造方法要求方法名必须跟类名一致。父类中被私有的成员, 往往都会提供对应的setXxx和getXxx方法,这些方法是公共的, 子类是可以继承使用的。
3、父类优先于子类加载到方法区中,方法区中会有所调用的类的成员变量和成员方法,当创建新对象的时候,在栈内存的主方法区创建引用,堆中会先加载父类变量和方法(虽然私有的成员变量我们看不到,但也会在堆中有),调用子类并不加载进堆中,get、set方法加载到栈中运行赋值。
4、类都是单继承的,可以多层继承,多层继承中,子类可以调用其上所有的父父父…的方法。 所有的类都直接或者间接的继承了Object类
随便创建一个类 Person p = new Person();
p.(equals、getClass、hashCode、notify、notifyAll、toString、wait)这些方法本自身就有,是Object类中的,所有的类都是Object的子类。
5、在使用子父类的时候,我们可以创建新类来继承其他,那么我们就直接继承了其他的类中的所有方法,而且还可以自己重写,补充。那如果继承的父类中有成员变量,我们在使用子类的时候,成员变量怎么继承,怎么使用?
6、setget方法加载方法dog方法关联getdog对象创建堆中开辟空间,虽然私有,但是父类方法也会存入堆内存中,
7、this和super的使用,注意this在某些情况下可以表示父类的引用
this: 代表本类对象的引用(地址)
* super: 代表父类对象的引用(地址)
* 成员变量:
* this.可以调用本类成员变量, 也可以调用父类成员变量
* 前提: 子父类中没有出现相同的成员变量
* super.只能调用父类的!!!!!!!!!!!!!!!!!
* 成员方法:
* this.可以调用本类成员方法, 也可以调用父类成员方法
* 前提: 子父类中没有出现相同的成员方法
* super.只能调用父类的!!!!!!!!
* this和super调用构造方法
* this() : 调用本类构造方法
* super() : 调用父类构造方法
* 子父类中构造方法的执行特点:
* 问题1: 子类和父类是谁应该先完成初始化?
* 一定是先完成父类的初始化, 子类在创建对象的时候, 有可能会使用到父类的成员
* 问题2: 初始化一个类, 或者说一个对象, 用的是哪一个方法?
* 构造方法
* 结论:
* 子类在创建对象的时候, 一定会先访问到父类的构造方法, 进行父类的初始化!
* 细节:
* 子类的所有[构造方法中]的第一行, 默认都会隐藏着一句super();
8、子类能使用的是父类中非私有的成员变量或成员方法
9、this和super是不能共存的
10、java.long包的可以直接调用
11、 注意super的使用,既沿袭了父类,又定义了子类自身的方法。
package com.heima.override;
public class TestOverride {
public static void main(String[] args) {
iOS7 i = new iOS7();
i.siri();
}
}
class Phone {
public void call(){
System.out.println("手机打电话");
}
class iOS6 extends Phone {
public void siri(){
System.out.println("speak english");
}
}
class iOS7 extends iOS6 {
// 当子类需要父类的功能, 但是子类方法的[功能主体]又有自己特有的实现方式, 这时候就可以对父类的方法进行重写
// 这样做既沿袭了父类的功能, 又定义了子类特有的内容
// @Override (注解) : 检测当前的方法是否是重写的方法
@Override
public void siri(){
super.siri(); //!!!!!!!!!!!!!!!!!!!!!
System.out.println("说中文");
}
}
12、多态,面向接口编程可以体会到价值
13、注意下面的例子,比较绕
package com.itheima;
public class Demo {
public static void main(String[] args) {
B b = new B(); //我是父类A的构造方法 --- 我就是迷惑 ---我是子类B的构造方法
}
}
class A {
public A() {
System.out.println("我是父类A的构造方法");
}
}
class B extends A{
public B () {
//super(); //默认存在
this(10);
System.out.println("我是子类B的构造方法");
}
public B (int num) {
//super();
System.out.println("我就是迷惑");
}
}
14、构造方法不能被继承
15、子类不能重写父类中私有(private)的方法。private<dafault<protected<public
16、多态中,父类引用只能看到内存堆中父类的空间,也就只能看到父类的成员变量,所以使用的就是父类的成员变量。(成员变量----编译看左边,运行看左边;成员方法----编译看左边,运行看右边)
多态创建对象调用成员的访问特点:
* 1. 成员变量 -> 使用的是父类的成员变量
* 编译看左边(父类), 运行看左边(父类)
* 因为是父类的引用, 所以只能看到堆内存中, super的一小块空间.
*
* 2. 成员方法 -> 使用的子类的成员方法
*
* 存在着一种动态绑定的机制
*
* 多态创建对象时, 调用成员方法, 编译时会检查父类中有没有这个方法
*
* 没有 : 编译失败
* 有 : 编译通过, 但是运行时执行子类的方法逻辑
*
* 编译看左边(父类), 运行看右边(子类)
17、多态的好处!!
package com.heima.duotai2;
public class TestDuotai {
/*
* 多态的好处:
*
* 1. 提高了代码的扩展性
*
* 扩展性:
* 可以将一个方法的形参定义为父类类型, 该方法就能接受这个父类的任意子类对象
*
* 一般在这个方法中, 我们只会调用共有的方法, 不会调用特有的方法.
*
* 为什么要设计动态绑定机制?
*
* 多态创建对象调用方法时, 编译看左边(父类), 运行看右边(子类)
* 编译时会检查父类中是否有此方法
* 没有: 编译失败
* 有 : 编译通过, 运行时执行子类的方法逻辑
*
* [如果]没有这种动态绑定机制, 即使方法能够接受任意子类对象, 调用的逻辑也就都是父类的, 这样做没有任何意义.
*
* 多态的弊端 :
*
* 不能调用子类特有的属性和行为.
*/
public static void main(String[] args) {
useAnimal(new Cat());
useAnimal(new Dog());
useAnimal(new Sheep());
}
// 提供一个可以使用猫对象的方法
public static void useAnimal(Animal a){ // Animal a = new Cat();
a.eat(); // Animal a = new Dog();
}
}
class Animal {
public void eat(){
System.out.println("动物吃饭");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("猫吃<・)))><<");
}
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("狗吃肉");
}
}
class Sheep extends Animal{
public void eat(){
System.out.println("羊吃草");
}
}
18、向上向下转型
package com.heima.duotai2;
public class TestSupeMan {
public static void main(String[] args) {
// 1. 超人乔庄成人
Person p = new SuperMan(); // 多态创建对象, 向上转型
System.out.println(p.name); // 编译看左边, 运行看左边
// 2. 调用谈生意的方法
p.谈生意(); // 编译看父类, 运行看子类, 子类的谈生意是从父类继承下来
// 3. 解除乔庄, 变回超人
SuperMan sm = (SuperMan) p; //强转!
sm.fly();
}
}
class Person {
String name = "克拉克";
public void 谈生意(){
System.out.println("谈生意");
}
}
class SuperMan extends Person {
String name = "超人";
public void fly(){
System.out.println("飞出去救人");
}
}
19、
package com.heima.test4;
public class Test4 {
/*
* >* 创建一个“动物类”,包含吃的方法
>* 创建一个“猫类”,包含吃的方法和 catchMouse
>* 创建一个“狗类”,包含吃的方法和 watchHome
要求, 定义一个方法, 可以接受狗对象的同时, 也能接受猫对象----多态^_^
方法内部调用共有的方法, 也要调用特有的方法
思路: 需要将该方法的形参定义为父类类型, 该方法就能接受这个父类的任意子类对象
*/
public static void main(String[] args) {
useAnimal(new Dog());
useAnimal(new Cat());
}
public static void useAnimal(Animal a){ // Animal a = new Dog();
// Animal a = new Cat();
a.eat();
// a.catchMouse(); 编译错误, 多态的弊端, 不能调用子类特有的属性和行为
// 向下转型
if(a instanceof Dog){
Dog d = (Dog) a;
d.watchHome();
}else if(a instanceof Cat){
Cat c = (Cat) a;
c.catchMouse();
}
}
}
class Animal {
public void eat(){
System.out.println("动物吃饭");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("猫吃猫粮");
}
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
class Dog extends Animal {
public void eat(){
System.out.println("狗吃肉");
}
public void watchHome(){
System.out.println("狗看家");
}
}