目录
1.继承基本介绍
2.继承关系中的成员访问
2.1就近原则
2.2继承关系中的构造方法
3.super和this
4.代码块和构造方法的执行顺序
4.1在没有继承关 系时的执行顺序。
4.2继承关系上的执行顺序
5.protected的 范围
6.继承的本质分析(重要)
7.final 关键字
1.继承基本介绍
当多个类存在相同的属性(变量)和方法时 , 可以从这些类中 抽象出父类, 在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来 声明继承父类即可。
继承主要解决的问题是:共性的抽取,实现代码复用。
基本语法:
class 子类 extends 父类{
}
(1) 子类又叫派生类。
(2)父类又叫基类超类。
子类会将父类中的成员变量或者成员方法继承到子类中
包括父类的private
但是父类的private,子类不能直接访问要通过方法。
总结:
子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问, 但是私有属性和方法不能在子类直接访 问,要通过父类提供公共的方法去访问
2.继承关系中的成员访问
2.1就近原则
先看两段代码
(1)
public class Test1 extends Base{
int a=199;
public static void main(String[] args) {
Test1 text=new Test1();
System.out.println(text.a);
text.fun();
}
public void fun(){
System.out.println(a);
System.out.println(this.a);
System.out.println(this.b);
System.out.println(super.a);
}
}
class Base{
int a=99;
int b=33;
}
(ps:super是关键字,该关键字主要作用:在子类方法中访问父类的成员。先知道这么多就行)
输出什么?
答案:
(2)
public class Text0 extends Base0{
public void method(){
System.out.println("我是Text0的method()");
}
public static void main(String[] args) {
Text0 t= new Text0();
t.method();
t.method2();
}
public void method2(){
super.method();
this.fun();
}
}
class Base0{
public void method(){
System.out.println("我是Base0的method()");
}
public void fun(){
System.out.println("我是Base0的fun()");
}
}
输出什么?
答案:
这说明了什么呢?我们可以得到什么结论?
成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找。也就是说 优先在子类中找,找到则访问,否则在父类中找,找到 则访问,否则编译报错。
2.2继承关系中的构造方法
子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。所以在构造子类对象时候 , 先要调用基类的构造方法,将从基类继承下来的成员构造完整 ,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整 。
先看代码
public class Base {
public Base(){
System.out.println("Base()");
}
public Base(int a){
System.out.println("Base(int a)");
}
}
public class Derived extends Base{
public Derived(){
// super(); // 注意子类构造方法中默认会调用基类的无参构造方法:super(),
// 用户没有写时,编译器会自动添加,而且super()必须是子类构造方法中第一条语句,
// 并且只能出现一次
System.out.println("Derived()");
}
public Derived(int a){
super(a);
System.out.println("Derived(int a)");
}
}
public class Test {
public static void main(String[] args) {
Derived d = new Derived();
Derived d2 = new Derived(4);
}
}
(1)子类必须调用父类的构造器, 完成父类的初始化。(2)如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表)(3)当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无 参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过。
3.super和this
(1) 都是 Java 中的关键字。(2) 只能在类的非静态方法中使用 ,用来访问非静态成员方法和字段。(3) 在构造方法中调用时, 必须是构造方法中的第一条语句 ,并且不能同时存在。
【不同点】
(1) this是当前对象的引用 ,当前对象即调用实例方法的对象, super相当于是子类对象中从父类继承下来部分成 员的引用。(2)在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性。
(3)在构造方法中:this(...)用于调用本类构造方法,super(...)用于调用父类构造方法,两种调用不能同时在构造 方法中出现。
(4)构造方法中一定会存在super(...)的调用,用户没有写编译器也会增加,但是this(...)用户不写则没有。
在继承中的关系
4.代码块和构造方法的执行顺序
4.1在没有继承关 系时的执行顺序。
class Person {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("构造方法执行");
}
{
System.out.println("实例代码块执行");
}
static {
System.out.println("静态代码块执行");
}
}
public class TestDemo {
public static void main(String[] args) {
Person person1 = new Person("bit",10);
System.out.println("============================");
Person person2 = new Person("gaobo",20);
}
}
1. 静态代码块先执行,并且只执行一次,在类加载阶段执行2. 当有对象创建时,才会执行实例代码块,实例代码块执行完成后,最后构造方法执行
4.2继承关系上的执行顺序
class Person {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("Person:构造方法执行");
}
{
System.out.println("Person:实例代码块执行");
}
static {
System.out.println("Person:静态代码块执行");
}
}
class Student extends Person{
public Student(String name,int age) {
super(name,age);
System.out.println("Student:构造方法执行");
}
{
System.out.println("Student:实例代码块执行");
}
static {
System.out.println("Student:静态代码块执行");
}
}
public class TestDemo4 {
public static void main(String[] args) {
Student student1 = new Student("张三",19);
System.out.println("===========================");
Student student2 = new Student("gaobo",20);
}
public static void main1(String[] args) {
Person person1 = new Person("bit",10);
System.out.println("============================");
Person person2 = new Person("gaobo",20);
}
}
1、父类静态代码块优先于子类静态代码块执行,且是最早执行2、父类实例代码块和父类构造方法紧接着执行3、子类的实例代码块和子类构造方法紧接着再执行4、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行
5.protected的 范围
package Dome2;
public class Text3 {
protected int x=100;
protected int y=110;
}
package Dome;
import Dome2.Text3;
public class Text2 extends Text3 {
public void fun()
{
System.out.println(super.x);
System.out.println(super.y);
System.out.println(x);
System.out.println(y);
}
public static void main(String[] args) {
Text2 t= new Text2();
System.out.println(t.x);
t.fun();
}
}
运行结果:
6.继承的本质分析(重要)
class Grandpa{
String name="爷爷";
}
class Father extends Grandpa {
String name="爸爸";
}
class Son extends Father {
String name="儿子";
}
当new Son的时候,内存的分布(重要):
注意:
(1)父类构造器的调用不限于直接父类!将一直往上追溯直到 Object 类(顶级父类)
(2)先加载类
Object- >Grandpa->Father- >Son
(3)就地赋值(常量)- >堆区储存的引用指向常量池
7.final 关键字
final int a = 10 ;a = 20 ; // 编译出错
2. 修饰类:表示此类不能被继承
final public class Animal {...}public class Bird extends Animal {...}// 编译出错Error :( 3 , 27 ) java : 无法从最终 com . bit . Animal 进行继
3. 修饰方法:表示该方法不能被重写
以上为我个人的小分享,如有问题,欢迎讨论!!!
都看到这了,不如关注一下,给个免费的赞