继承
在旧事物的前提下,让新事物保持旧事物的特性,并泛生出新事物自己独有的特性。在java中,继承是对某一批类的抽象,提高了代码的复用性。
继承就是在A类(基类)上,泛生出B类(派生类)。B类会自动继承A类的方法和变量(稳性的,无需手动添加),在B类中可以调用A类的方法和变量。
java中只允许单继承,但可以多实现(接口)。单继承是指一个派生类只能显性的继承一个基类(object是所有类的父类),但一个基类可以被多个派生类所继承
1.继承的步骤
-
在派生类名后使用
extends
再加上基类名例:
public class typeClassName extends typeClassName
-
在派生类中,可以用与基类成员方法名相同的方法,去覆盖掉基类的同名成员方法
注:基类的构造器不能被派生类继承,但在派生类的构造器中会隐式的调用父类中的无参构造器,也可以用super去调用基类的构造器
2.Object类
在java中所有类都会间接或直接继承于Object类,在java文档中可以看到所有类的最低层都是Object。而我们自己创建的类在编译后也jdk会自动默认的帮我们继承Object
Object中提供了如:toString()、equals()、getClass()等方法,用于被后面的派生类继承
3.Super关键字
同this
差不多一个意思,但super
代表的是基类,所以它只能出现在派生类中(如果没有显式的继承那它将代表Object)
public class Person{
protected String name = "Tom";//修饰符protected是把数据保护起来,不被除子类外其他包的类直接调用
//public Person(){}
public Person(String name){ this.name = name; }
public void toName(){
System.out.println(this.name);
}
//被private修饰的成员不能被继承
private void print(){
System.out.println("Person!!!");
}
}
public class Student extends Person{
private String name = "Lisi";
//编译报错,在下面的构造器中会隐式的调用基类的无参构造器 super(); ,但基类中没有手动编写无参构造器
public Student(){
//super();隐式的
}
//编译通过,下面构造器中显式的调用父类的有参构造器。
public Student(){
super("Tom");
}
@Override
public void toName(){
System.out.println(this.name);
}
public void tes(){
System.out.println(this.name);//Lisi
System.out.println(super.name);//Tom
this.toName();//Lisi
super.toName();//Tom
super.print();//编译报错
}
}
注:同this()
一样,不管是显式还是隐式的super()
,super语句一定要出现在派生类构造器中第一行代码。所以this()
和super()
不能同时使用,因为它们都要出现在第一行代码位置。
4.方法重写
是把基类中的方法在派生类中重新实现。
方法用@Override标注的,说明该方法是从基类重写的,IDEA中通过快捷键Alt+Insert
-> Override Methods...
或者Control+O
@Override
public void toName(){}
4.1哪些不能被重写
- 基类的静态方法不能被派生类重写为非静态方法;//编译出错
- 基类的非静态方法不能被派生类重写为静态方法;//编译出错
- 派生类可以定义与基类的静态方法同名的静态方法(但是这个不是覆盖)
- 基类的私有方法不能被重写,基类的私有方法不能被直接访问的
4.2重写的事项
-
方法名必须相同
-
参数列表也必须相同
-
访问修饰符只能扩大,不能被缩小。重写后的方法访问范围要比重写前小
public > protected > default > private
-
抛出异常类型的范围只能缩小,不能扩大
如:ClassNotFoundException ---> Exception 这就是扩大,不能扩大
-
返回类型可以相同,也可以不同;如果不同,那重写后的方法返回类型必须重写前方法返回类型的子类型
4.3作用
继承后,原有的功能并不一定能满足后继的开发需求,所以需要把方法进行重写
4.4方法重写与重载的区别
方法重写只存在于继承,而重载是在同一个类中发生的;方法重载参数列表必须不相同;
public class Father{
protected String name = "Tom";
public void toName(){
System.out.println(this.name);
}
}
public class Son extends Father{
private String name = "lism";
//方法重写
@Override
public void toName(){
System.out.println(super.name);
System.out.println(this.name);
}
}
==================================================================================
5.protected关键字
2022/2/9 对于protected
关键字鄙人理解错误了
修饰符protected
是除自身和派生类可访问,其他包下的类不可以访问。被修饰的成员也会被继承,如果派生类重写了protected
修饰的成员方法,那在该派生类的同一个包的类也可以访问
//在同一包下的派生类和基类
public class A{
protected int age;
protected void f(){
System.out.println("age is " + age);
}
}
public class B extends A{}
//与基类不同包的派生类
public class C extends A{}
//与基类同一包下的测试类
public class BaseText{
public static void main(String[] args){
A a = new A();//可以正常访问
a.age = 10;
a.f();//10
B b = new B();//可以正常访问
b.age = 20;
b.f();//20
C c = new C();//可以正常访问
c.age = 30;
c.f();//30
}
}
//与基类不同包下的测试类
public class BaseText{
public static void main(String[] args){
A a = new A();
a.age = 10;//报错,'age'在'BaseText.AB.A'中有受保护的访问权
a.f();
B b = new B();
b.age = 20;//报错,'age'在'BaseText.AB.A'中有受保护的访问权
b.f();
C c = new C();
c.age = 30;//报错,'age'在'BaseText.AB.A'中有受保护的访问权
c.f();
}
}
派生类成员方法调用protected
修饰的方法
//重写派生类C,并访问由基类A继承过来的f()方法
public class C extends A{
public void toF(){
System.out.println("is to f!!");
f();
}
}
//与基类、派生类不同包的测试类
public class BaseText{
public static void main(String[] args){
C c = new C();
c.toF();
/*运行结果:
is to f!!
age is 0*/
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!