继承
概念
继承时表示类与类的一种关系,通过extends进行实现,继承的类被称为子类,被继承的类称为父类,基类或者超类。在内存中表示就是子类存储空间含有一部分存储父类信息,是包含关系。当子类继承父类后,就可以直接使用父类公共的属性和方法了。因此,用好这个技术可以很好的我们提高代码的复用性。注解代码会在放最后,
主要通过注解解释,作者自己的理解。
javaA为父类javaB为子类,在同一包下;javaC(子类)与父类在不同包下
注意点一,方法修饰符(public)
如果父类方法范围过小,则不会被继承,因为在不同模块下,如果使用继承需要导入父类import demo.javaA
;,然而父类有些方法的作用范围无法跨域包,则无法通过子类调用父类这些方法。如缺省;
/**
* 简述在继承中缺省存在的问题
* 1.javaA被com包下的javaB继承
* 2.缺省,修饰方法只作用在相同包下的任意文件,而javaB是在com包下
* javaC在继承JavaA是有导包,import demo.javaA;在继承时编译javaA时并没有缺省方法
* 所以不继承
* 3.protected修饰:不同包下的子类可以使用该方法,对象不能调用
*/
//javaA
void Packege(){
System.out.println("缺省继承");
}
通过@Override报错显示不属于方法重写。在javaC()子类可以写入,虽然不满足方法重载的求,所以可以理解为该方法内没有此功能。
子类继承,通过
注意点二,静态(重点)
首先了解静态。重点理解一句话静态方法属于类,非静态方法属于对象。调用static修饰都要注意,
例如:在继承父类的静态方法,子类也存在该代码,则会根据static属性,直接属于子类,下面通过@Override
有总结。
/**
* 静态方法注意点
* static静态修饰。静态成员变量和静态成员方法是属于类的。非静态成员方法和变量是通过对象调用,
* 在继承中javaB继承javaA,在父类中的静态成员方法会继承给子类。
* 但是方法重写(是对父类的功能扩展)是应用于多态,方法 :编译看左,运行看右 减少代码耦合。
* 变量 :编译运行都看左
* 静态方法,变量是属于这个类的,他在继承中会直接属于子类,所以通过@Override进行验证,定义上有着冲突。
* 原因:static修饰的方法会直接属于类而且在子类静态重写会直接将同名的父类的静态属性和静态方法隐藏。
* 验证:父类的静态方法已存在于子类,不过(static)直接属于子类如果在子类中将静态方法的static修饰取掉就会直接报错
*如果向上转型Father father = new Son(),这时候father只会调用父类自己的静态属性和静态方法,不会调用子类的静态属性和静态方法
* 原因,静态方法是通过类名调用。通过对象调用不建议
*/
public static void jingtai(){
System.out.println("staticA");
}
简述静态方法不能使用非静态方法和变量(方法区):方法区随着类的加载,会在方法区先将静态方法,变量在方法区加载。而对象的创建是在堆内存中进行创建对象,静态方法属于类,在对象声明之前执行在方法区加载静态代码的读取。如果对象没有被创建,代码读取会存在问题https://blog.csdn.net/qq_35499112/article/details/84886871
从这篇大佬文章可以从内存上解释。
注意点三:方法重写
子类继承父类,子类也可以又有自己的想法,可以对方法进行重写,子类方法重写不应影响父类。父类的私有属性,子类无法调用。
/**
* 方法重写
* 子类在继承父类的情况下,对父类方法进行重写,不会父类的代码产生影响。
* 父类中私有的成员变量和方法,对于子类虽然被继承,但是没有访问权限。
*/
@Override
public void use(){
System.out.println("22222");
super.use();
}
注意点四:多态调用
多态使用 javaA A = new javaB();
当然也可以javaB() B = new javaA ;
牢记执行方法,编译看左,执行看右,对于变量,全看左。解释一下:多态使用是为了增加代码松耦合,而且父类存在的地方子类都能使用,后期就是接口功能,类实现,通过接口调用。所以注意就是因为编译看左,子类含有子类方法,而编译时该对象没有该方法,会报错。
/**
* 子类独有方法在多态使用存在的问题
* 该方法是子类自己的方法,检验 javaA A = new javaB();
* 方法编译看左 : 左侧父类没有use1扩展方法,所以在编译时A.use1,会找不到这个方法进行报错。
* 原因:多态的使用,广泛是作用代码松耦合,因为继承关系父类拥有的方法,类都有(接口,抽象类也是),所以通过把功能实现与功能明明分开
* 可以直接带哦用方法名调用。减少功能代码块和项目的联系。
* 父类形参可以接受所有的子类参数
* @param a
*/
public void use1(String a){
System.out.println("子类B扩展方法:"+a);
}
调用:
显示父类javaA没有该方法,也就是编译时是看左边。后面是全部代码。代码少主要是理解。
小知识点(对象初始化)
这个知识点知道,但是没怎么注意,这是在看到一个题才发现没好好理解。
包结构
javaA()
package demo;
public abstract class javaA {
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public void use(){
System.out.println("1111");
}
/**
* 简述在继承中缺省存在的问题
* 1.javaA被com包下的javaB继承
* 2.缺省,修饰方法只作用在相同包下的任意文件,而javaB是在com包下
* javaC在继承JavaA是有导包,import demo.javaA;在继承时编译javaA时并没有缺省方法
* 所以不继承
* 3.protected修饰:不同包下的子类可以使用该方法,对象不能调用
*/
void Packege(){
System.out.println("缺省继承");
}
/**
* 静态方法注意点
* static静态修饰。静态成员变量和静态成员方法是属于类的。非静态成员方法和变量是通过对象调用,
* 在继承中javaB继承javaA,在父类中的静态成员方法会继承给子类。
* 但是方法重写(是对父类的功能扩展)是应用于多态,方法 :编译看左,运行看右 减少代码耦合。
* 变量 :编译运行都看左
* 静态方法,变量是属于这个类的,他在继承中会直接属于子类,所以通过@Override进行验证,定义上有着冲突。
* 原因:static修饰的方法会直接属于类而且在子类静态重写会直接将同名的父类的静态属性和静态方法隐藏。
* 验证:父类的静态方法已存在于子类,不过(static)直接属于子类如果在子类中将静态方法的static修饰取掉就会直接报错
*如果向上转型Father father = new Son(),这时候father只会调用父类自己的静态属性和静态方法,不会调用子类的静态属性和静态方法
* 原因,静态方法是通过类名调用。通过对象调用不建议
*/
public static void jingtai(){
System.out.println("staticA");
}
}
javaB()
public class javaB extends javaA{
public javaB() {
}
/**
* 方法重写
* 子类在继承父类的情况下,对父类方法进行重写,不会父类的代码产生影响。
* 父类中私有的成员变量和方法,对于子类虽然被继承,但是没有访问权限。
*/
@Override
public void use(){
System.out.println("22222");
super.use();
}
/**
* 子类独有方法在多态使用存在的问题
* 该方法是子类自己的方法,检验 javaA A = new javaB();
* 方法编译看左 : 左侧父类没有use1扩展方法,所以在编译时A.use1,会找不到这个方法进行报错。
* 原因:多态的使用,广泛是作用代码松耦合,因为继承关系父类拥有的方法,类都有(接口,抽象类也是),所以通过把功能实现与功能明明分开
* 可以直接带哦用方法名调用。减少功能代码块和项目的联系。
* 父类形参可以接受所有的子类参数
* @param a
*/
public void use1(String a){
System.out.println("子类B扩展方法:"+a);
}
}
javaC()
import demo.javaA;
public class javaC extends javaA {
//@Override
void Packege(){
System.out.println("缺省继承");
}
}
实现类
import demo.javaA;
import demo.javaB;
public class demoExtends {
public static void main(String[] args) {
/**
* 一个知识点:对象初始化
* 在创建对象类时,成员信息通常是 private 数据类型 成员变量名;然后通过方法调用。
* 我们可以发现,我们并没有对成员变量进行赋值,所以是系统在调用构造方法时,会对成员变量进行初始化,
* 一般会直接初始化为null但如果类对象中对对象实例化,则会在构造方法执行前,对变量进行实例化。
*/
javaA A = new javaB();
//A.use1("11111");
};
}