Bootstrap

Java入门第二章——面向对象:面向对象

面向对象【Java语言的核心机制】

  • 面向对象三大特性:封装、继承、多态。【所有面向对象的语言都有】

  • 面向对象和面向过程区别:

*面向对象:主要关注对象【独立体】能完成那些功能。【例如独立显卡开发思路】

优点:耦合度低,扩展力强。更容易解决现实世界中更复杂的业务逻辑,组件复用性强。

缺点:前期投入成本高,需要进行独立体的抽取,大量系统分析与设计。

*面向过程:主要关注实现具体过程,因果关系【例如集成显卡的开发思路】

优点:对业务逻辑比较简单的程序,可以到达快速开发,前期成本较低。

缺点:采用面向过程的方式开发很难解决非常复杂的业务逻辑,另外面向过程的方式导致软件元素之间的“耦合度”非常高,只要其中一环出现问题,整个系统受影响,导致最终的软件扩展力差。且由于没有独立体概念,无法到达组件复用。

*C语言是纯面向过程的,C++半面向对象,Java纯面向对象。

  • 面向对象开发软件生命周期【整个生命周期贯穿使用OO面向对象】

-面向对象分析:OOA

-面向对象设计:OOD

-面向对象编程:OOP

  • 类和对象

-类:在现实世界不存在的,是抽象出来的概念。类代表了一个事物。在现实世界当中,对象A和对象B之间具有共同特征,进行抽象出来一个模板,这个模板称为类。

-对象:对象是实际存在的个体,现实世界当中实际存在。

*类到对象的过程称为“实例化”,对象又被称为实例【instance】,对象到类的过程称为“抽象”。

*一个类主要描述:状态+动作。

状态——>类的属性。描述状态信息。

动作——>类的方法。描述动作信息。

1.面向对象特性:封装

封装优点:

*封装之后,对于封装的事物来说,看不到事物复杂的一面,只能看到简单的一面。复杂性封装,对外提供简单的操作入口。

如:照相机。照相机实现原理较为复杂,但是操作照相机非常便捷。

*封装之后才会形成真正的“对象”,真正的“独立体”。

*封装意味着程序可以重复使用,且这个事物适应性较强,在任何场合都可以使用。

*封装之后,对于事物本身,提高了安全性。【安全级别高】

1.封装步骤:

(1)对所有属性私有化,使用private关键字进行修饰,private表示私有的,修饰的所有数据只能在本类中访问。

(2)对外提供简单的操作接口,也就是如果外部程序想要访问对象中的属性,必须通过这些简单入口进行访问:

​ -对外提供两个公开的方法,分别是set方法和get方法

​ -想修改属性调用set方法

​ -想读取属性调用get方法

(3)set方法命名规范:public void set+属性名首字母大写(形参){}

//例如
public void setAge(int a){
    age = a;
}

(4)get方法命名规范:public ElemType get+属性名首字母大写(){} 【ElemType 表示数据类型】

//例如
public int getAge(){
    return age;
}

注:

—setter 和 getter方法没有static 关键字

—有static关键字修饰的方法调用:类名.方法名(实参);

—没有static关键字的方法调用:引用.方法名(实参);

2.set和get

在操作入口只能通过set和get方法进行访问后,在set方法和get方法执行过程中可以进行安全过滤。

//例如:要在修改数据中判断输入的参数是否在一个区间范围
public void setAge(int a){
    if(a<0 || a>150){
        System.out.println("输入的数据有误");
        return;//结束调用
    }
    //程序能执行到这里,说明a合法
    age = a;
    
}

例子:

//封装一个用户类
public class User{
    //属性私有化
    private int age;
    //一个错误的例子,形参名字设置跟属性一样,会报错
    //    public void setAge(int age){
    //        age = age;  //java有就近原则,这里的age是局部变量的age。
    //    }
    
    //setter方法
    public void setAge(int a){
        //编写业务逻辑代码进行安全控制
        // age = a;
        if(a < 0 || a>150){
            System.out.println("您提供的年龄不合法");
            return;
        }
        //程序若执行到这,说明a合法,进行赋值运算。
        age = a;
    }

    //getter方法
    public int getAge(){
        return age;
    }
}
public class UserTest{
    public static void main(String[] args){
        //创建User对象
        User user = new User();
        //System.out.println(user.age);
        //编译报错,age已经属性私有化了,外部程序不能直接访问。
        
        //修改数据
        user.setAge(-100); //设置了安全过滤,数字小于0未修改age值
        //读取
        System.out.println(user.getAge()); //0
        
        //修改数据
        user.setAge(23);
        //读取
        System.out.println(user.getAge()); //23
    }
}

2.构造方法

关于java类中的构造方法:

1.构造方法又被称为构造函数/构造器/Constructor

2.构造方法语法结构:

[修饰符列表] 构造方法名(形式参数列表){ 构造方法体; }

3.回顾普通方法的语法结构:

[修饰符列表] 返回值类型(形式参数列表){ 方法体; }

4.对于构造方法来说:"返回值类型"不需要指定,并且也不能写void。只要写上void,方法就成为普通方法。

5.对于构造方法来说:构造方法的方法名必须和类名保持一致。

6.构造方法的作用:构造方法存在的意义是,通过构造方法的调用可以创建对象。同时初始化实例变量的内存空间。

7.构造方法调用:

​ -普通方法调用:方法修饰符中有static的时候:” 类名.方法(实参列表) “ 、方法修饰符列表中没有static的时候:“ 引用.方法名(实参列表) ”

​ -构造方法调用:new 构造方法名(实参列表)

8.每个构造方法执行结束之后都有返回值,但"return 值;" 这样的语句不需要写。构造方法结束的时候java程序自动返回值。

并且返回值类型是构造方法所在类的类型。 由于构造方法返回值类型就是类本身,所以返回值类型不需要编写。

9.当一个类中没有定义任何构造方法的话,系统默认给该类提供一个无参数构造方法,这个构造方法被称缺省构造器。

10.当一个类显示的将构造方法定义出来了,那么系统则不再默认为这个类提供缺省构造器。开发中手动为当前类提供无参数构造方法。因为无参数构造方法比较常用。

11.构造方法支持重载机制。在一个类当中编写多个构造方法,这多个构造方法显然已经构成重载机制。

例子:

public class User(){
    public User(){
        System.out.println("这是一个无参构造器");
    }
    public User(int i){
        System.out.println("这是一个带int类型的构造器");
    }
    public User(String name){
        System.out.println("这是一个带String类型的构造器");
    }
    public User(int i ,String name){
        System.out.println("这是一个带int类型和String类型的构造器");
    }
}

public class Test(){
    public static void main(String[] args){
        User u1 = new User();  //这是一个无参构造器
         User u1 = new User(1);  //这是一个带int类型的构造器
         User u1 = new User("name");  //这是一个带String类型的构造器
         User u1 = new User(1,"name"); //这是一个带int类型和String类型的构造器
    }
}

3.参数传递

  • java在方法调用涉及到参数传递时传递方式:值传递

例子:

public class Test{
    public static void main(String[] args){
        int i = 10;
        //这里的调用属于传值调用
        add(i);  //等同于add(10);
        System.out.println("main——> "  + i);  //main——>10
    }
    public static void add(int i ){
        i++;
        System.out.println("add——> " + i);  //add——>11
    }
}

java语言放中,方法调用的时候涉及到参数传递的问题:参数传递实际上只传递了变量中保存的具体值。

public class Test02 {
    public static void main(String[] args){
        User u = new User(20);
         //这里u的值是一个引用。而这里的u的值是一个java对象的内存地址。
        add(u); //等同于add(0x1234);
        System.out.println("main——>" + u.age);  //main——>21
    } 
    public static void add(User u){
        u.age++;//所以这里u里边的属性更改的时候,会被更改。而u本身存储的地址不会被更改。
        System.out.println("add ——>" + u.age); //add——>21
    }
}
class User{
    int age;
    public User(int i){
        age = i;
    }
}

综上:方法调用的时候,涉及到参数传递的问题,传递的时候,java只遵循一种语法机制。就是将变量中保存的“值”传递过去,只不过有时候这个值可能是一个字面值(基本数据类型),有的时候这个另一个java对象中内存地址(引用数据类型)。

4.this关键字

  • 关于Java语言中this关键字:
  1. this关键字,翻译为:这个

  2. this是一个引用,是一个变量。this变量中保存了内存地址指向自身,this存储在JVM堆内存java对象内部。

  3. 创建的每个对象,都有this。

  4. this可以出现在“实例方法"当中,指向代表当前正在执行的动作对象。

  5. this在多数情况下可以省略不写。

  6. this不能使用在带有static的方法当中。

在这里插入图片描述

【例】

public class Customer{
    String name;  //这里定义了一个实例变量
    
    //定义一个不带static的方法
    public void shopping(){
        //this关键字可以省略
        System.out.println(name + "在购物");//编译通过
        //完整写法
        //System.out.println(this.name + "在购物");
    }
    //定义一个带static的方法
    public static void doSome(){
        //带有static方法是通过类名访问,也就是说这里没有对象
        //编译报错:System.out.println(name + "在购物");
        //name在Customer对象中是一个实例变量,而在doSome中未创建对象时候,直接使用name是使用当前对象的name则访问不到name。
        
        //需要创建对象后才能使用
        Customer c = new Customer();
        System.out.println(c.name);
    }
    
}

【例】

public class ThisTest{
    int i = 10;
    
    //带有static的方法,JVM负责调用main方法。
    //调用方式:ThisTest.main(String[]);
    public static void main(String[] args){
        //System.out.println(i);  编译错误
        //System.out.println(this.i);  编译错误
        
        //若想访问i
        ThisTest tt = new ThisTest();
        System.out.println(tt.i); // 10
    }
}

【例】

public class ThisTest{
    public static void main(String[] args){
        ThisTest.doSome();
        doSome();
        
        //doOther();  //编译错误
        //this.doOther();  //编译错误
        
        //创建对象
        ThisTest tt = new ThisTest();
        //调用对象的实例变量
        tt.run();
    }
    
    public static void doSome(){
        System.out.println("do some");
    }
    //实例变量
    public void doOther(){
        System.out.println("do other");
    }
    //实例变量
    public void run(){
        System.out.println("run");
        //在实例变量中,执行到实例变量时一定存在对象。也就是这里一定有this。
        //所以在这里调用当前对象的doOther()方法。
        doOther();
        //完整写法:this.doOther();
    }
}
  • 结论:带有static的方法中,不能直接访问实例变量和实例方法。

    ①因为实例变量和实例方法都需要对象存在

    ②static的方法中是没有this,也就是当前对象不存在

    ③所以无法访问当前对象的实例变量和实例方法。

【例】

public class ThisTest{
    //实例变量
    String name;
    //实例方法
    public void doSome(){
        
    }
    public static void main(String[] args){
        //System.out.println(name);  无法访问实例变量
        //doSome();  无法调用实例方法
        
        ThisTest tt = new ThisTest();
        System.out.println(tt.name);  //通过对象访问实例变量
        tt.doSome();  //通过对象访问实例方法
    }
}
  • 用来区分局部变量和实例变量时," this. "不能省略

【例】

//语法格式:  this.
public class User{
    private int id;  //实例变量
    
    public void setId(int id){
        //this.id指的是实例变量
        //id指的是局部变量
        this.id = id;
    }
}
  • this可以使用在构造方法当中,通过当前构造方法调用其他构造方法。

【例】

//语法格式 this(实参)
public class Date {
    private int year;
    private int month;
    private int day;
    
    //需求:调用无参构造方法默认为“2001-01-01”
    public Date(){
        //原设置
        //this.year = 2001;
        //this.month = 01;
        //this.day = 01;
        
        //如果用new构造方法,会导致引用时候构造了两个对象。
        //可以使用this直接调用其他构造方法,且不会创建新的对象。
        //且this()只能出现在第一行
        this(2001,01,01);
    }

    public Date(int year,int month,int day){
        this.year = year;
        this.month = month;
        this.day = day;
    }
}

5.练习

public class test06 {

    //带有static的方法
    public static void method1(){
        //访问doSome
        //使用完整方式调用
        test06.doSome();
        //使用省略方式调用
        doSome();

        //访问doOther
        //使用完整方式调用
        test06 t = new test06();
        t.doOther();

        //访问i
        //使用完整方式调用
        System.out.println(t.i);
    }

    //没有static的方法
    public void method2(){
        //访问doSome
        //使用完整方式调用
        test06.doSome();
        //使用省略方式调用
        doSome(); //this.doSome();

        //访问doOther
        //使用完整方式调用
        this.doOther();
        //省略方式
        doOther();

        //访问i
        //使用完整方式调用
        System.out.println(this.i);
        //省略方式
        System.out.println(i);
    }
    //主方法
    public static void main(String[] args) {
      //要求:调用method1
        //使用完整方式调用
        test06.method1();
        //使用省略方式调用
        method1();

      //要求:调用method2
        //使用完整方式调用
        test06 t = new test06();
        t.method2();

    }

    //没有static的变量
    int i = 10;
    //带有static的方法
    public static void doSome(){
        System.out.println("do some!");
    }
    //没有static的方法
    public void doOther(){
        System.out.println("doOther");
    }
}

6.static关键字

  • static(静态的)修饰做为静态资源使用,可修饰方法也可修饰变量。
  • 当所有对象的某个属性都是一样时,建议定义为静态变量,节省内存开销。
  • 静态变量在类加载中的时候初始化,访问的时候不需要创建对象。直接“ 类名. ”访问
//创建一个中国人类
public class Chinese{
    //身份证号
    String id;
    //姓名
    String name;
    //由于中国人每个人的国籍都是一样的,所以使用静态变量定义
    //国籍
    static String country = "中国"public Chinese(){
        
    }
    public Chinese(String id,String name){
        this.id = id;
        this.name = name;
    }
}

public class ChineseTest{
    public static void main(String[] args){
        Chinese ice = new Chinese("1","冰");
        System.out.println(ice.id + "," + ice.name); //1,冰

        Chinese coffice = new Chinese("2","咖啡");
        System.out.println(coffice.id + "," + coffice.name);//2,咖啡

        //静态变量在类加载中的时候初始化,访问的时候不需要创建对象。直接“ 类名. ”访问
        System.out.println(Chinese.country); //中国
    }
}
  • 用static关键字定义“静态代码块”,静态代码块在类加载时执行一次(在main方法前执行)。例如类加载的时刻执行代码完成日子记录。
  • 静态代码块通常用来完成预备工作,先完成数据的准备工具,例如:初始化连接池,解析XML配置文件等。
public class test02 {
    static {
        System.out.println("类加载-->1");
    }
    static{
        System.out.println("类加载-->2");
    }

    public static void main(String[] args) {
        System.out.println("main方法");
    }
}
/*输出结果:
类加载-->1
类加载——>2
main方法
*/
  • 静态方法中无法直接访问实例变量和实例方法。

7.继承

  • 面向对象三大特征:封装、继承、多态

  • 继承基本的作用:代码复用,有了继承之后才有了方法的覆盖和多态机制。

  • 继承语法:[修饰符列表] class 类名 extends 父类名{ 类体 = 属性 + 方法 }

  • Java当中继承只能支持单继承,一个类只能继承一个类,但是可以间接继承。C++中支持多继承。

  • 可继承:私有的不支持继承、构造方法不支持继承、其他数据都可以被继承。

  • 如果Java语音中一个类没有继承任何类,该类继承JAVASE中java.lang.Object类。

【例子】

//账户类
public class Account{
    private String actno;
    private double balance;
    public Account(String actno, double balance) {
        this.actno = actno;
        this.balance = balance;
    }
    public Account() {
    }
    public String getActno() {
        return actno;
    }
    public double getBalance() {
        return balance;
    }
    public void setActno(String actno) {
        this.actno = actno;
    }
    public void setBalance(double balance) {
        this.balance = balance;
    }
}
//继承账户类的信用账户
public class CreditAccount extends Account{
    private double credit;
    public CreditAccount(){
        super();
    }
    public double getCredit() {
        return credit;
    }
    public void setCredit(double credit) {
        this.credit = credit;
    }
}
//测试类
public class ExtendsTest {
    public static void main(String[] args) {
     CreditAccount act = new CreditAccount();
     act.setActno("act-001");
     act.setBalance(-1000.0);
     act.setCredit(0.99);
        System.out.println(act.getActno() + "," + act.getBalance()+","+act.getCredit());
        //act-001,-1000.0,0.99
    }
}

8.方法覆盖

  • 方法覆盖:又称方法重写(override)

  • 方法覆盖:当父类中方法无法满足当前子类业务需求,子类有必要将继承的方法进行重新编写。

  • 方法覆盖发生在具有继承关系的父子类之间,返回值类型相同、方法名相同、形参列表相同。

public class Animal{
    public void move(){ System.out.println("动物在移动"); }
}
public class Bird extends Animal{
    public void move(){ System.out.println("鸟在飞翔"); }
}
public class Cat extends Animal{
    public void move(){ System.out.println("猫在走猫步"); }
}
public class OverrideTest {
    public static void main(String[] args) {
        Animal a = new Animal();
        a.move(); //动物在移动
        Cat c = new Cat();
        c.move();//猫在走猫步
        Bird b = new Bird();
        b.move();//鸟在飞翔
    }
}
  • 私有方法不能继承,所以不能覆盖;构造方法不能继承,所以不能覆盖。

9.多态

  • 多态概念

    向上转型:子类型→父类型(自动类型转换)

    向下转型:父类型→子类型(强制类型转换)

    向上转型和向下转型都需要有继承关系。

//动物类
public class Animal{
    public void move(){ System.out.println("动物在移动"); }
}
//猫类继承动物类
public class Cat extends Animal{
    //重写父类继承过来的方法
    public void move(){ System.out.println("猫在走猫步"); }
    //子类对象特有,不是继承父类的方法
    public void catchMouse(){ System.out.println("猫抓老鼠"); }
}

public class Test{
    public static void main(String[] args){
        //父类型引用指向子类型对象,这里作为向上转型
        Animal c1 = new Cat();
        //这里把Cat类型强制转换为Animal,然后才调用move方法。
        //且这里的c1是Animal类型,所以引用不了catchMouse()方法
        c1.move();  //猫在走猫步
    }
}
  • 以上如果需要调用catchMouse方法,需要将Animal(父类)转化为Cat(子类)。即向下转型。

    当调用的方法是子类型特有的,在父类型不在,必须进行向下转型。

public class Test{
    public static void main(String[] args){
        //父类型引用指向子类型对象,这里作为向上转型
        Animal c1 = new Cat();
        //这里把Cat类型强制转换为Animal,然后才调用move方法。
        //且这里的c1是Animal类型,所以引用不了catchMouse()方法
        c1.move();
        
        //需求:当c1需要调用Cat中特有的方法时,进行强制类型转换(向下转换)
        Cat c2 = (Cat) c1;
        c2.catchMouse(); //猫抓老鼠
        
    }
}
  • 当一个子类型被向上转型为父类,父类又进行向下转型为其他子类型。会编译报错。
//动物类
public class Animal {
    public void move(){ System.out.println("动物在移动"); }
}
//鸟类继承动物类
public class Bird extends Animal{
    //重写从父类中继承的方法
    public void move(){ System.out.println("鸟在飞翔"); }
}
//猫类继承动物类
public class Cat extends Animal{
    //重写从父类中继承过来的方法
    public void move(){ System.out.println("猫在走猫步"); }
}
public class Test{
    public static void main(String[] args){
        Animal a3 = new Bird();
        Cat c3 = (Cat) a3;
        //编译异常:Exception in thread "main" java.lang.ClassCastException:
        //也就是类型转换异常
    }
}
  • java.lang.ClassCastException :这种为类型转换异常,做强制类型转换时会发生。

  • 使用“ instanceof ”运算符可以避免ClassCastException异常。

    语法格式: 引用 instanceof 数据类型名。

    这个运算符执行结果是布尔类型。

 c1 instanceof Animal
 //运行结果true 表示 c1是一个Animal类型
 //运行结果false 表示 c1不是一个Animal类型

【instanceof例子】

//动物类
public class Animal {
    public void move(){ System.out.println("动物在移动"); }
}
//鸟类继承动物类
public class Bird extends Animal{
    //鸟类特有的方法
    public void fly(){ System.out.println("鸟飞啦"); }
}
//猫类继承动物类
public class Cat extends Animal{
    //猫类特有的方法
    public void catchMouse(){ System.out.println("猫抓老鼠"); }
}
public class Test{
    public static void main(String[] args){
         Animal a = new Bird();
        if(a instanceof Cat){ //如果a是Cat类型
            Cat c = (Cat)a;
            c.catchMouse();
        }else if(a instanceof Bird){  //如果a是鸟类型
            Bird b = (Bird)a;
            b.fly();
        }
    }
}

//最终运行结果:鸟飞啦

10.final关键字

  • final修饰的类无法被继承
public final class A{  }
//public class B extends A{ }  
//这里A类被final修饰,所以B无法继承A。会报错
  • final修饰的方法无法被覆盖
public class C{
    public final void m1(){  }
}
public class D extends C{
    //public void m1(){  }
    //这里m1方法给final修饰,所以无法重写,会报错
}
  • final修饰变量,一旦赋值后不可重新被赋值【二次赋值】
public class A{
    public static void main(String[] args){
        //可先定义再赋值
    final int a;
    a=100;
    //可定义直接赋值
    final int b = 100;
    
    //a=20;
    //b=2;
    //由于a和b被final修饰,所以无法重新赋值
    }
    
}
  • final修饰实例变量,必须手动赋值,不可采用系统默认值【因为实例变量有默认值,final一旦修饰变量则无法赋值,所以定义实例变量时必须赋值】
public Class A{
    //final int a;
    //因为实例变量有默认值,final一旦修饰变量则无法赋值,所以定义实例变量时必须赋值
    final int a = 10;
    
    final int b;
    public FinalTest(){
        //这里在构造方法中赋值,是可行的
        this.b = 200;
    }
    public static void main(String[] args){
        
    }
}
  • final修饰的引用无法一旦指向某个对象之后,不能再指向其他对象【被指向的对象无法被垃圾回收期回收】
public class User{
    int id;
    public User(int id){
        this.id=id;
    }
}
public class FinalTest{
    public static void main(String[] args){
        //创建一个新对象
        User u = new User(30);
        //创建另一个新对象用u引用
        //到此,上边的User(30)对象已成垃圾数据,等待垃圾回收器回收
        u=new User(50);
        
        //用final修饰用户对象
        final User user = new User(35);
        //final修饰引用。被指向的对象无法被垃圾回收期回收
        //user= new User(40); 引用不能重新被赋值,出错
        user.id=50;  //使用的是引用里边的变量,内部的内存是可以修改的。
    }
}
  • final修饰的实例变量,这种变量一般和static配合使用,称为“常量“。
//常量的语法格式定义:public static final 类型 常量名 = 值
//规范:常量名字全部大写,每个单词之间使用下划线连接

//中国人类
class Chineses{
    public static String GUO_JI = "中国";
}

public class FinalTest{
    public static void main(String[] args){
        System.out.println(Chinese.GUO_JI);
    }
}

11.package,import

  • package(包),java引入package机制将不同功能的类分别放到不同软件当中,方便管理与维护。

  • 定义package:

    -在java源程序的第一行上编写package语句。

    -只能编写一个语句

    -语法:package 包名

  • 包名的命名规范:公司域名(倒序) + 项目名 + 模块名 + 功能名;

    -需要全部小写,需要遵守标识符命名规则。

    -一个包对应一个目录。

package com.thetest.study.javasestudy;

public class Test{
    public static void main(String[] args){
        System.out.println("Test01 是一个方法执行");
    }
}
//使用package机制后,类名不是Test,而是:com.thetest.study.javasestudy.Test
  • import语句用来导入其他类,同一个包下的类不需要导入,不在同一个包下需要手动导入

  • import语法格式:

    -import 类名;

    -import 包名.*;

  • import语句编写在package语句下面,class语句上面。

12.访问控制权限

  • 访问控制权限修饰符:用来控制元素的访问范围,如public、protected、private

    —public:表示公开的,任何位置都可访问

    —private:表示私有的,只能在本类中访问

    —protected:表示受保护的,**同包下、子类(包括其他包)**中可以访问

    —缺省的(没有上面关键字的):只能在同包下访问

//在一个包中
package com.thetest.study.javasestudy;
public class User{
    public static void main(String[] args){
        //受保护的
        protected int i = 10;
        //缺省的
        int j = 20;
    }
}
//在另一个包下
package com.thetest.study.javasestudy2;
import com.thetest.study.javasestudy.User;
public class Test exnteds User{
    public void m(){
        System.out.println(i);//可以访问
        //System.out.println(j);不可访问
    }
        
}
  • 普通类只能使用public、缺省进行修饰【内部类(在类中定义的类)除外】

13.super关键字

  • super()只能出现在构造方法第一行,通过当前的构造方法调用“父类”中的其他构造方法,目的是代码复用。
public class superTest {
    public static void main(String[] args) {
        new B();
    }
}
class A{
    //一个类如果提供了一个构造方法,那么系统不会默认提供无参构造方法
    public A(int i){

    }
}
class B extends A{
    public B(){
        //由于A类需要有一个int参数,所以继承父类需要super(int);
        //子类如果没有写super(),会默认在第一行有。
        //这里默认会有一个super();所以这里会发生错误。所以要填一个super(int);
        super(100);
        //也就是super(100);不写,会默认有super();会导致调用一个无参构造方法,而A类只有一个有参构造方法,所以会报错。
        System.out.println("B类的无参构造方法");
    }
}
  • this()和super()不能共存。都是只能存在构造方法第一行。

  • “ super. ”在大部分情况下可以省略,当父类和子类有同名属性,或者同样方法,想要在子类中访问父类时“ super. ”不能省略。
    语法格式:

    -super.属性名 【访问父类的属性】

    -super.方法名(实参) 【访问父类的方法】

    -super(实参) 【调用父类构造方法】

——本章节为个人学习笔记。学习视频为动力节点Java零基础教程视频:动力节点—JAVA零基础教程视频

;