JavaSE:继承、重写、构造器、成员变量的初始化

一、构造器

1.构造器:constructor,他是类的第三个成员。

2.作用:

(1)和new关键字一起,就可以创建对象。

(2)在创建对象的同时,给对象的实例变量初始化。

3.构造器和方法长得很像,又把构造器称为构造方法。

(1)构造器的名字和类名必须完全一致,包括大小写。

(2)构造器没有返回值,也不写void。

(3)构造器的修饰符只有权限修饰符,没有其他修饰符。

语法格式:

[修饰符] class 类名{

-【权限修饰符】 类名(形参列表){

}

}

4.构造器的其他特点

(1)任何类都有构造器

(2)如果程序员没有编写构造器,那么编译器就会自动无参构造

(3)如果程序员手动编写构造器,那么编译器就不会自动添加无参构造。

(4)一个类可以有多个构造器,他们构成重载。

set:为其中一个变量赋值/修改其中一个变量

get: 获取其中一个变量的值

构造器:创建对象,每次new都是新的对象,在创建对象的同时给成员变量赋值

例子:
public class TestConstructor {
    public static void main(String[] args) {
        Student stu = new Student();

        Scanner input = new Scanner(System.in);
    }
}
class Student{

    Student(){
        //无参构造
    }

    Student(String name, int age){
        //有参构造
    }
}

二、继承

1.面向对象的基本特征之一。

2.代码的复用和代码的扩展就会用到复用。

3.语法:

关键字:extends

语法格式:【修饰符】class子类名 extends 父类名{

}

4.继承的特点:

(1)子类中会继承父类所有的成员变量、成员方法等,但是父类中私有的成员变量成员方法等在子类无法直接使用。

(2)子类不会继承父类的构造器

(3)子类虽然不能继承父类的构造器,但是”必须“在子类的的构造器中调用父类的构造器;

默认情况下,子类的构造器中,调用的是父类的无参构造

子类的构造器中可以使用super()调用父类的无参构造;

如果没有写super(),也没写super(实参列表),默认找到父类的无参构造。

如果父类没有无参构造,就必须在子类的构造器中手动调用父类的有参构造: super(实参列表) 该实参列表要与父类被调用的有参构造的形参列表一一对应

(4)java只支持单继承

一个子类只能有一个直接的父类。

(5)父类还可以有父类

(6一个父类支持很多个子类)

举例
public class TestInherited {
    public static void main(String[] args) {
        //创建Student对象
        Student stu = new Student();//使用无参构造
//        Student stu2 = new Student("张三",23);//子类没有编写有参构造,不会从父类继承有参构造

        stu.setName("张三");
        stu.setAge(23);

        System.out.println(stu.getInfo());
        stu.test();

        Student stu2 = new Student("李四",24);
        System.out.println(stu2.getInfo());
    }
}

class Person{
    String name;
    private int age;

    public Person(String name) {
        this.name = name;
    }
    public Person(String name, int age) {
        System.out.println("父类的有参构造");
        this.name = name;
        this.age = age;
    }

    public Person() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getInfo(){
        return "姓名:" + name + ",年龄:" + age;
    }
}
//需求:声明一个学生类,教师类
/*
class Student{
    private String name;
    private int age;
    private int score;
    //...
}
class Teacher{
    private String name;
    private int age;
    private double salary;
    //...
}*/
class Other{

}
//Student是子类,Person是父类
class Student extends Person{
    public Student(){
       // super("张三",23);//语法正确,就是有点奇怪,把name和age就是初始化为常量值
        super();//调用父类的无参构造
    }
    public Student(String name, int age){
        super(name, age);//调用父类的有参构造
    }

    public void test(){
//        System.out.println("name =" + name);
        System.out.println("name =" + getName());
    }
}
//Teacher是子类,Person是父类
class Teacher extends Person{
    public Teacher(String name, int age){
        super(name, age);
    }
}

三、重写

重载:Overload
重写:Override

1.重写

(1)什么情况下重写?

子类继承父类的方法时,会继承父类的所有方法。

注:父类私有的方法,子类中无法直接使用

子类继承父类的方法之后,觉得父类的方法实现不适合子类,那么子类可以选择对它进行重写

(2)如何重写

1.方法名必须相同

2.形参列表必须相同

(如果形参列表不同就是重载)

3.返回值类型

基本数据类型和void:必须相同

引用数据类型子类<=父类

4.修饰符:

权限修饰符:子类>= 父类

其他修饰符: static 不能重写

(3)当子类重写了父类的某个方法,但是子类中又想要调用这个被重写的方法时,必须加”super.“

class Animal{
    protected void eat(){
        System.out.println("吃东西");
    }

    public Animal method(){
        return null;//返回空,null可以赋值给任意引用数据类型
    }

    public static void test(){
        System.out.println("父类的静态方法");
    }
}
class Dog extends Animal{

    public void eat(){
        //调用父类的eat()
        super.eat();
        System.out.println("啃骨头");
    }
/*    public String eat(){
        System.out.println("啃骨头");
        return "骨头渣子";
    }*/

    public Dog method(){
        return null;//返回空,null可以赋值给任意引用数据类型
    }

    public static void test(){
        System.out.println("子类的静态方法");
    }
}

四、关键字:this和super

1、this:当前对象
(1)在构造器中表示正在new的对象
(2)在成员方法中表示 调用这个方法的对象

2、用法
(1)this.成员变量
在构造器、非静态方法和代码块中,当成员变量与局部变量重名时,在成员变量的前面加this.,重名时不能省略this.
(2)this.成员方法 (非常少)
在非静态方法和代码块中,表示调用当前对象的其他方法,可以加this.,也可以省略
(3)this()或this(实参列表)
位置:只能出现在构造器的首行
表示调用本类的其他构造器
this():表示调用本类的无参构造
this(…):表示调用本类的有参构造

目的是:代码复用

三、找寻顺序和原则 ==> 就近原则和追根溯源原则
1、this()和this(实参列表):只在本类中找对应构造器
2、super()和super(实参列表):只在直接父类找对应构造器
3、在方法中出现对变量的引用,既没有this.变量,又没有super.变量
(1)先看局部变量
(2)如果没有,看本类的成员变量
(3)如果没有,看父类的成员变量,而且这父类不仅限于直接父类,前提条件是可见
(4)如果没有,报错
4、在构造器或方法中出现this.变量
(1)先看本类的成员变量
(2)如果没有,看父类的成员变量,而且这父类不仅限于直接父类,前提条件是可见
(3)如果没有,报错
5、在构造器或方法中出现super.变量
(1)先看直接父类中有没有该成员变量,前提条件是可见
(2)如果没有,去父类的父类中查找,前提条件是可见
6、在构造器或方法中出现对方法的调用,没有加this.方法,也没有加super.方法,也没有 类名.方法,也没有 对象名.方法
(1)先从本类的方法列表中查找
(2)如果没有,看父类,而且这父类不仅限于直接父类,前提条件是可见
7、在构造器或方法中出现this.方法的调用
(1)先从本类的方法列表中查找
(2)如果没有,看父类,而且这父类不仅限于直接父类,前提条件是可见
8、在构造器或方法中出现super.方法的调用
(1)在直接父类中查找该方法,前提条件是可见
(2)如果没有,去父类的父类中查找,前提条件是可见

这里要注意一个问题,super.方法,一旦某个父类中找到,就不会往上追溯了。

public class TestThisSuper {
    public static void main(String[] args) {
        Employee e1 = new Employee();
        Employee e2 = new Employee(1,"张三");
        Employee e3 = new Employee(1,"张三","10086","123456");
    }
}

class A{
    public void method(){
        System.out.println("a");
    }
}
class B extends  A{
    public void method(){
        System.out.println("b");
    }
}

class C extends  B{
    public void method(){
        //访问A类的method方法
        super.method();
//        super.super.method();//错误,无法直接访问A类的method,因为B类重写了,对于C来说,只能看到B类重写的method
    }
}

class Employee{
    private int id;
    private String name;
    private int age;
    private String tel;
    private String cardId;
    private String address;

    public Employee() {
        System.out.println("一个员工对象创建了");
    }

    public Employee(int id, String name) {
        this();
        this.id = id;
        this.name = name;
    }

    public Employee(int id, String name, String tel, String cardId) {
        this(id,name);
        this.tel = tel;
        this.cardId = cardId;
    }

    public Employee(int id, String name, int age, String tel, String cardId, String address) {
        this(id,name,tel,cardId);
        this.age = age;
        this.address = address;
    }
}
class Manager extends Employee{
    private double bonus;

    public Manager() {
        //省略super()
    }

    public Manager(int id, String name, double bonus) {
        super(id, name);//必须在子类构造器首行
        this.bonus = bonus;
    }

    public Manager(int id, String name, String tel, String cardId, double bonus) {
        this(id, name,bonus);
        this.bonus = bonus;
    }

    public Manager(int id, String name, int age, String tel, String cardId, String address, double bonus) {
        super(id, name, age, tel, cardId, address);
        this.bonus = bonus;
    }
}

五.成员变量的初始化

1、成员变量是有默认值
byte,short,int,long:0
float,double:0.0
char:\u0000
boolean:false
引用数据类型:null

2、成员变量分为
(1)静态变量:所有对象共享,和类共存亡
(2)实例变量:每一个对象独立的,和对象共存亡

它什么时候初始化?它初始化的方式有哪些?

3、静态变量的初始化方式和时机
(1)静态变量是在类初始化时完成初始化的
我们在使用一个类时,先要把类加载到内存,然后完成类的初始化,才能使用这个类中的方法等
(2)类初始化的过程,其实是在执行一个()方法
中的cl:代表class,init代表:initialize
方法不是程序员收到编写的,而是编译器自动生成的,每一个类都有,也只有一个。
它的代码是由:
①静态变量的显式赋值语句
②静态代码块的语句
按编写的顺序组装而成。

4、静态代码块
作用:为静态变量初始化
因为实际开发中,很少编写 static int a = getNum()这种方式为静态变量赋值,
我们静态变量的值又不是常量值,可能需要读取配置文件来为静态变量初始化,
这个时候就需要一大段代码为静态变量完成赋值,那么我们就可以把这样的代码放在静态代码块中。

public class TestInitialize {
    public static void main(String[] args) {
        Demo.method();//跨类调用静态方法,使用“类名.”
    }
}

class Demo{
    static{
        System.out.println("静态代码块");
    }

    static int a = getNum(); //通过调用getNum方法为a静态变量赋值,是为了看到初始化的过程


    public static int getNum(){
        System.out.println("getNum方法被调用了");
        return 10;
    }

    public static void method(){
        System.out.println("静态方法");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值