首页 > 编程语言 >Java拾贝第三天——面向对象2

Java拾贝第三天——面向对象2

时间:2023-10-16 16:37:08浏览次数:35  
标签:Java 拾贝 Person class 面向对象 Student 父类 public name

继承性

面向对象三大特性:封装性,继承性,多态性
继承的作用是避免出现大幅度的相同代码,提高代码的复用性。

//现有一个Person类,拥有name,age属性
class Person {
    private String name;
    private int age;
  //构造方法和setter,getter

现在有一个Student类,它和Person类的属性大幅度相同,仅多出一个grade属性

class Student {
    private String name;
    private int age;
    private int grade
  //构造方法和setter,getter

难道像上面一样又写一遍?如果不止Student类,Teacher类更多的...类呢?

为了提高代码复用性且解决上述问题,继承(extends)出现了!

继承格式如下:
class 子类 extends 父类{}

子类也叫拓展类,父类也叫超类,基类

相应的,子类会继承父类所有非私有的属性和方法

public class test3 {
    public static void main(String[] args) {
        Student s = new Student("小红", 20, 99);//报错,因为父类的属性private
    }

}
class Person {
    private String name;
    private int age;
  //构造方法和setter,getter
}
class Student extends Person {
//拥有父类的name和age属性吗?
    private int grade;

  public Student(String name, int age, int grade) {
       this.grade = grade;
    }
  //setter,getter
}

为了让子类可以访问父类属性,我们需要把属性或方法定义为protected

public class test3 {
    public static void main(String[] args) {
        Student s = new Student("小红", 20, 99);
    }

}
class Person {
    protected String name;
    protected int age;

  public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
  //setter,getter
}
class Student extends Person {
//拥有父类的name和age属性
    protected int grade;

  public Student(String name, int age, int grade) {
       this.grade = grade;
    }
  //setter,getter
}

运行上述代码,会出现在Student的构造方法中,无法调用Person的构造方法的错误。

这是因为在Java中,任何类的构造方法都会默认隐式的调用其父类的无参构造方法。
super关键字

//所以Student类的构造方法实际上是这样
  public Student(String name, int age, int grade) {
       super();
       this.grade = grade;
    }

但Person类定义了有参构造方法,并没有显式定义无参构造方法,所以编译无法通过。

解决方法是使用super调用父类的有参构造方法。

public class test3 {
    public static void main(String[] args) {
        Student s = new Student("小红", 20, 99);
    }

}
class Person {
    protected String name;
    protected int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    //setter,getter
}
class Student extends Person {
    //拥有父类的name和age属性
    protected int grade;

    public Student(String name, int age, int grade) {
        super(name, age);//调用父类有参
        this.grade = grade;
    }
    //setter,getter
}

子类实例化过程
构造方法那里说到,任何类的实例化都会调用一次构造方法。
那么继承了父类的子类的实例化过程是怎么样的呢?

public class test3 {
    public static void main(String[] args) {
        Student s = new Student("小红", 20);
        System.out.println(s.getAge);
    }

}
class Person {
    protected String name;
    protected int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("父类构造方法");
    }
    //setter,getter
}
class Student extends Person {
    //拥有父类的非私有属性
    public Student(String name, int age) {
        super(name, age);
        System.out.println("子类构造方法");
    }
    //拥有父类的非私有方法
}
/*
父类构造方法
子类构造方法
20
*/

可以看到实例化子类时会优先实例化(也叫初始化)其父类。

Object
任何类都继承Object类,Java中不允许多继承

class Student extends Person1,Person2{}//这是错误的

但允许多层继承

class Person1{}

class Person2 extends Person1{}

class Student extends Person2{}

上述继承树关系如下:
image

向上转型,向下转型

正常来说实例一个Person对象它指向的应该是Person类

Person p=new Person();

实例一个Student对象它指向的应该是Student类

Student s=new Student();

如果是实例化Person对象指向Student类呢?

public class test3 {
    public static void main(String[] args) {
        Person p=new Student();//Person指向Student
	//它可以调用子类learn方法吗?
    }
}

class Person {
    public Person() {
        System.out.println("父类的无参构造");
    }

    public void say() {
        System.out.println("父类say方法");
    }
}

class Student extends Person {

    public Student() {
        System.out.println("子类的无参构造");
    }
    public void learn() {
        System.out.println("子类learn方法");
    }
}

因为Student继承自Person,所以它可以安全的赋值给变量p。这种安全的赋值称之为向上转型

//向上转型
Person p=new Student();

但变量p只能使用父类Person类的方法,也就是说它没有子类的learn方法。

向下转型
和向上转型相反,如果把父类赋值给子类就是向下转型。

public static void main(String[] args) {
        Student s =new Person();
        s.learn();
    }

甚至连编译都无法通过!大多时候的向下转型都会失败!
一般来说子类都是父类的拓展,也就是子类属性和方法都比父类要多,这些多的功能不能凭空出现。所以会向下转型失败。

instanceof关键字
instanceof用于判断变量是否是指定类型或者其子类,一般构成一个布尔表达式

变量 instanceof 类名==布尔表达式
if(变量 instanceof 类名){};

栗子:

Person p = new Person();
System.out.println(p instanceof Person); // true
System.out.println(p instanceof Student); // false 
System.out.println(p instanceof Object); // true 所有类都继承Object

Student s = new Student();
System.out.println(s instanceof Person); // true 子类属于父类
System.out.println(s instanceof Student); // true

Student n = null;
System.out.println(n instanceof Student); // false
System.out.println(n instanceof Object); // false

如果一个变量指向null,使用instanceof判断永远为false。

方法的重写

在Java拾贝第二天方法中提到了方法的重载,基于继承Java提供了重写的概念。

即子类重写父类的方法,方法名,返回值类型,传参均相同就是重写

public class test3 {
    public static void main(String[] args) {
       Student s =new Student();//实例化子类时会优先实例化父类
       s.say();
    }
}

class Person {
    public Person() {
        System.out.println("父类的无参构造");//实例化任何类都会调用其无参构造方法
    }
    public void say() {
        System.out.println("父类say方法");
    }
}
class Student extends Person {
    @Override
    public void say() {
        System.out.println("子类重写父类say方法");
    }
}
/*
父类的无参构造
子类重写父类say方法
*/

在转型那里我们知道一种安全的转型,即向上转型

public class test3 {
    public static void main(String[] args) {
       Person p =new Student();
       p.say();//输出结果是什么呢?
    }
}

class Person {
    public void say() {
        System.out.println("父类say方法");
    }
}
class Student extends Person {
    @Override
    public void say() {
        System.out.println("子类重写父类say方法");
    }
}

多态性

标签:Java,拾贝,Person,class,面向对象,Student,父类,public,name
From: https://www.cnblogs.com/Ocraft/p/17767180.html

相关文章

  • Java Assert断言使用
    目录断言所谓的assertion,是jdk1.4后加入的新功能。作用它主要使用在代码开发和测试时期,用于对某些关键数据的判断,如果这个关键数据不是你程序所预期的数据,程序就提出警告或退出。后续当软件正式发布后,可以取消断言部分的代码。java中使用assert作为断言的一个关......
  • java web
    0.了解maven1.了解http协议2.了解tmcat的作用3.了解请求响应4.了解分层解耦5.了解servlet原理Maven为java世界引入了一个新的依赖管理系统jar包管理jar包升级时修改配置文件即可......
  • Java设计模式
    七大设计原则开闭原则:是指一个软件实体如类、模块和函数应该对扩展开放,对修改关闭依赖倒置原则:是指设计代码结构时,高层模块不应该依赖底层模块,二者都应该依赖其抽象而不依赖于具体。单一职责原则:是指一个Class/Interface/Method只负责一项职责。接口隔离原则:是指用多个专......
  • Java常见集合类学习笔记
    List1.ArrayListVectorLinkedList区别​ ArrayList和Vector底层实现基本相同,都是基于数组实现的,只是Vector的方法用synchronized修饰;所以ArrayList是线程不安全的,Vector是线程安全的。​ LinkedList底层基于双向链表实现,方法没有用synchronized修饰,线程不安全。2.数组和......
  • Java大文件上传详解及实例代码
    前言:上周遇到这样一个问题,客户上传高清视频(1G以上)的时候上传失败。一开始以为是session过期或者文件大小受系统限制,导致的错误。查看了系统的配置文件没有看到文件大小限制,web.xml中seesiontimeout是30,我把它改成了120。但还是不行,有时候10分钟就崩了。同事说,可能是客户这里服......
  • java -jar命令及SpringBoot通过java -jav启动项目的过程
    本篇文章将为大家讲述关于SpringBoot项目工程完成后,是如何通过java-jar命令来启动的,以及介绍java-jar命令的详细内容,对SpringBootjava-jav启动过程感兴趣的朋友跟随小编一起看看吧本篇文章将为大家讲述关于SpringBoot项目工程完成后,是如何通过java-jar命令来启动的......
  • Java 常用中间件
    Java常用中间件1、网关Nginx、Kong、Zuul、Gateway2、缓存Redis、MemCached、OsCache、EhCache3、搜索ElasticSearch、Solr4、熔断Hystrix、resilience4j5、负载均衡DNS、F5、LVS、Nginx、OpenResty、HAproxy6、注册中心Nacos、Eureka、Zookeeper、Redis、Etcd、Cons......
  • day02-面向对象
    面向过程&面向对象面向过程--线性步骤清晰简单,第一步做什么,第二步做什么面向过程适合处理一些较为简单的问题面向对象物以类聚,分类的思维模式,思考问题首先会解决问题需要那些分类,然后对这些分类进行单独思考。最好,才对某个分类下的细节进行面向过程的思索。面向对象适合处......
  • java实现大文件传输
    简介在现代互联网中,我们经常需要传输大文件,例如视频、音频或者大型数据文件。传输大文件需要考虑诸多因素,例如网络延迟、带宽限制和传输安全性。在本文中,我们将介绍如何使用Java实现大文件传输,并提供相应的代码示例。文件传输协议在进行大文件传输之前,我们需要选择合适的传输协议......
  • java导出占位符word模板
    实际项目中,便于维护模板,采用直接word里面制作占位符来导出更为直观,而不是将word做成tpl模板。使用XWPFDocument(这种解析xlsx或者docx)和HWPFDocument(这种解析xls或者doc)。代码如下:写磁盘代码:点击查看代码//创建Word模板文件:在开始代码编写之前,我们需要准备一个Wor......