Java面向对象基础

目录

JavaSE面向对象基础

重点回顾

面向对象概论

概述

面向对象的概念

对象

消息和方法

类和对象之间的关系

封装

封装有三大好处

四个关键字

继承

继承的优点

继承的缺陷

特殊关键字

包package

基础练习

抽象

面向对象和面向过程的区别

具体练习

构造器方法

析构器

总结继承

继承的特性


JavaSE面向对象基础

重点回顾

数组的创建:

  • 动态创建:数据类型[] 数组变量名 = new 数据类型[]

  • 静态创建:数据类型[] 数组变量名 = {元素1,元素2,...}

  • 动态创建并赋初始值:数据类型[] 数组变量名 = new 数据类型[]{元素1,元素2,...}

数组特点:

  • 只能存储相同类型的数据

  • 数组中的值可以重复

  • 数组的长度是固定的

  • 数组是连续的内存空间

相关的算法

  • 冒泡排序

  • 二分法查找

系统与定义类的引入

  • 基本类型及其包装

  • 字符串类型

  • 日期类型基础

  • 随机数

  • Math.random()

    • Random r = new Random()

练习:

假设有n级台阶,一个人可以一次上1级或者2级台阶,问有多少种上法

面向对象概论

【考试题】

面向对象的三大基本特征是:封装、继承、多态

  • 封装隐藏了类的内部实现,从而可以在不影响使用者的前提下改变类的内部结构,同时保护了数据

    • 隐藏功能或者信息的细节,使用者只关注功能的使用,而不需要关心实现细节

  • 继承是为了重用父类代码,同时为实现多态性作准备

    • 关键子extends,子类可以继承父类的成员变量和成员方法

    • Java采用的是单根继承体系

  • 多态性是发送消息给某个对象,让该对象自行决定响应何种行为。通过将子类对象引用赋值给超类对象引用变量来实现动态方法调用。

    • 一个事物可以有多种表现形式

    • 体现形式常见的有三种

      • 夫类型引用子类对象

      • 方法重写

      • 方法重载

面向对象三大特征的优缺点

  • 设计目标

  • 可维护性高

  • 重用性高

  • 扩展性增强

  • 执行效率

概述

面向过程是一种自上而下的程序设计方法,主要思路专注于算法的实现

自上而下的设计方法,设计者用一个main函数概括整个应用需要做的事情,然后把main方法拆解成不同的步骤,对应不同的函数

过程式的特征是以函数为中心,用函数作为划分程序的基本单位;数据在设计中处于从属的位置 过程式设计的优点是易于理解和掌握,这种逐步细化问题的设计方法与大多数人的思维方式比较接近复杂是,要做到这一点比较困难;当开发需求变化时,以前对问题的理解会变得不在适用

软件代码的重用性很差,即使重用,也是简单的复制和拷贝,代码数量急剧增加。而不是直接继承和应用

面向过程的方法将数据和过程分离,使得数据的改变很可能带来代码的变化

面向对象是一种自上而下的程序设计方法,以数据为中心,类是表现数据的单位,是划分程序的基本单位

面向对象是自上而下的特性,允许开发者从问题的局部开始,在开发过程中逐步加深对系统的理解。需求变化会作用到系统开发本身,形成一种螺旋式的开发方式

面向对象设计中,类分装了数据,而类的成员函数作为其对外的接口,抽象地描述类,用类将数据和操作这些数据的函数放在一起,这就是面向对象设计方法的本质

面向对象的概念

OO面向对象Object Oriented是软件开发方法

  • 面向对象是一种新兴的程序设计方法,或者是一种新的程序设计规范paradigm,其基本思想是使用对象、类、继承、封装、消息等基本概念来进行程序设计

  • 从现实世界中客观存在的事物(即对象)出发来构造软件系统,并且在系统构造中尽可能运行人类的自然思维方式

  • 开发一个软件是为了解决某些问题,这些问题所设计的业务范围称作该软件的问题域。其应用领域不仅仅是软件,还有计算机体系结构和人工智能等。

  • 面向对象的思想已经涉及到软件开发的各个方面。如面向对象的分析(OOA,Object Oriented Anaiysis),面向对象的设计(OOD,Object Oriented Design),以及我们经常说的面向对象的编程实现(OOP, Object Oriented Programming)

  • OOP使得现实世界中的概念在计算机程序中编程模块,它包括构造程序的特征以及组织数据和算法的机制

面向对象是一种对现实世界理解和抽象的方法

  • 传统的程序设计主张将程序看作一系列函数的集合,或者直接就是一系列对电脑下达的。面向对象程序设计中的每一个对象都应该能够接受数据,处理数据并数据传达给其他对象,一次它们都可以被看作一个小型的“机器”,即对象

  • OOP语言有三大特征:封装、继承以及多态,所有这些特征与类的概念息息相关的

  • 面向对象是指一种程序设计范型,同时也是一种程序开发的方法。对象是指另类的集合。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性

    • 对象、类、实体之间的关系和面向对象的问题求解思维方式

对象

对象是要进行研究的任何事物,从最简单的数据到复杂的飞机等均可看作对象,它不仅能表示具体的事物,还能表示抽象的规则、计划或事件。对象是一个客观存在的、唯一的实体,是一个类的动态实例,拥有自己的标识、数据与行为

  • 在现实世界中:是客观世界中的一个实体

  • 在计算机世界中:是一个可标识的存储区域

  • 现实世界中的所有事物都是对象

    • 对象都具有某些特征,并展现某些行为

对象的状态和行为

  • 对象具有状态,一个对象用数据值来描述他的状态

  • 对象还有操作,用于改变对象的状态,对象及其操作就是对象的行为

  • 对象实现了数据和操作的结合,是数据和操作封装与对象的统一体中

对象的两个要素

  • 属性:用于描述对象静态特征(结构特性)的一个数据项,描述一个人可用姓名、性别、身份证号等属性

  • 方法(也称服务):用于描述对象动态特征(行为特征)的一个操作系列

    • 每个人都具有工作、学习等行为特征

  • 对象将数据和施加于数据上的操作打包成一个不可分割的最基本的模块,使得仅有该类的有限个方法才可以操纵,改变这些数据

用Java语言对现实生活中的事物进行描述,通过类的形式来体现

  • 类是具有共同属性和行为的对象的抽象,具有相同特征(数据元素)和行为(功能)的对象的抽象就是类

  • 对象的抽象就是类,类的具体就是对象,也可以说类的实例是对象

  • 类实际上就是一种数据类型

    • 类是用于组合各个对象所共有的操作和属性的一种机制

    • 类是具有相同属性和行为的一组对象的集合

      • 类具有属性,他是对象的状态的抽象,用数据结构来描述类的属性

      • 类具有操作,它是对象的行为的抽象,用操作名和实现该操作的方法来描述

  • 类可以定义为数据和方法的集合,类也称为模板,因为它提供了对象的基本框架

    • 一旦定义类后,就可以用这种新类来创建该类的对象

      • 类就是对象的模板(template)

      • 而对象就是类的一个实例(instance)

消息和方法

  • 对象之间进行通信的结构叫做消息。发送一条消息至少要包括说明接受消息的对象名、发送给该对象的消息名(即对象名、方法名)

  • 类中操作的实现过程叫做方法,一个方法有方法名、返回值、参数、方法体

类和对象之间的关系

类是事物的描述

  • 类是Java程序的核心,它定义了对象的形状和本质,可以用类来创建对象。当使用一个类创建了一个对象时,通常说给出了这个类的一个实例

  • 类由类声明和类体构成,一般命名方法为:首字母大写,大写字母分词

    class calssName{
        类体:
    }

  • 类包括数据成员(数据、属性)和成员方法(函数)。一般建议数据成员应该是通过函数(方法)访问的

  • 对象是类的实例,就是应用中定义的某个类的变量,例如Person p = new Person();p就是对象

  • 类是和问题域相关的具有相同属性和行为的对象的抽象;对象是类事物的实例,在节哀吧中通过new来创建的

封装

在面向对象程序设计方法中,封装Encapsulation是指一种减抽象性函数接口的实现细节部分包装、隐藏起来的方法

  • 封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问

    • 反射机制

  • 要访问该类的代码和数据,必须通过严格的接口控制。

  • 封装最主要的功能在于能修改自己的实现代码,而不用修改那些调用代码的程序片段

  • 适当的封装可以让程序码更容易理解于维护,也增强了程式码的安全性

    //第一步是确定研究的目标对象---可以区分的独立个体
    //需要方法和属性
    class Student{
        //成员属性---静态特征的描述
        private boolean sex; //一般使用私有属性,共有的get/set方法
        //成员方法---提供的功能描述
        public boolean getSex(){
            return this.sex;
        }
        //不允许修改sex所以不提供set方法
        protected void setSex(boolean sex){ //如果在特殊情况下允许修改,可以使用范围限定词进行表示
            this.sex = sex;
        }
    }
    ​
    //构建对象
    Student s1 = new Student();
    s1.setSex(true);
    s1.setSex(false);  //是否允许取决于范围限定词

封装有三大好处

  • 良好的封装能够减少耦合

  • 类内部的结构可以自由修改

  • 可以对成员进行更精准的控制

  • 隐藏信息,实现细节

四个关键字

用于进行访问控制

//一个文件可以有无数个类,但是只能有一个public class公共类
public class Student{
    //成员属性,类中包含哪些静态特性取决于问题本身
    private Long id;  //private只能在当前类中直接访问
    protected String name;  //protected可以在同包或者子类中直接访问
    int age;  //没有范围限定词,默认或者package限定词,只能在同包中直接访问
    public double salary;  //public到处可见
    
    //一般规则是私有属性,共有的get/set方法
}

辅助记忆表格

当前类内同包子类到处
privateT
无范围限定词(package)TT
protectedTTT
publicTTTT

类定义规则:要求类内高聚合,类间弱耦合

  • 封装确实可以使容易的修改类的内部实现,而无需修改使用了该类的客户代码

例子:计算装修费用

查找名词:房间(多个墙)墙(长、高)窗户(长、宽)......

继承

继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

继承就是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但是不能选择性地继承父类

继承就是is-a的相互关系

继承的优点

  • 将所有的子类的共同属性放入父类,实现代码共享,避免重复,提高开发效率

  • 可以使用修改扩展继承而来的实现比较简单

继承的缺陷

  • 父类变子类必须变

  • 继承破坏了封装,对于父类而言,它的实现细节对于子类来说都是透明的

  • 继承是一种强耦合的关系(耦合:物理学上指两个或两个以上的体系或两种运动形式间通过相互作用而彼此影响以至联合起来的现象。)

特殊关键字

包package

包是类或者接口的容器,是一个用于避免命名冲突的名空间,是一个逻辑命名的概念,与具体的物理位置无关

在具体实现中,包名称经常和目录名称对应

什么是包

  • 包是类的组织方式,提供命名空间和访问控制

  • 类似于文件系统的组织

声明包中的类package

语法:package 包名称;

  • 声明包要求是源代码文件的第一个语句。包定义之前可以添加注释信息

  • 程序中最多只能有一条package语句,没有包定义的源代码文件成为默认包中的一部分

    • //默认包中的类可以访问其他命名包或者只能同包访问,其他包不能访问默认包中的类
      public class A1{
          public void cc(){
              System.out.println("Hello word!")
          }
      }

  • 程序中如果有package语句,该语句必须是第一条语句(前边只能有注释或者空行)

  • 包的名称命名规则

    • 全小写

    • 使用域名反转的方式定义,例如baidu.com,定义包名称为:com.baidu

      • 如果细节还可以引入功能定义部分

包的作用

  • 包能将相关的源代码文件组织在一起

  • 包减少了命名冲突带来的问题

  • 可以使用package指明源文件中的类属于哪个具体的包

包的使用

  • 如果其他人想使用包中的类,则需要使用全名

    import java.util.Date;
    ​
    public class A{
        public static void main(String[] args){
            Date now = new Date();   //使用类的简称Date,而不是全名称java.util.Date
        }
    }
    ​
    //用法2:全称
    java.util.Date now = new java.util.Date();  //不需要import

  • 为了简化书写,Java提供了import语句:import package_name.*;

    import java.util.*;
    ​
    //使用java.util包中的所有类都不需要使用import java.util.类名

  • 引入包中的某一个类:import java.util.ArrayList;

引入包import

  • Java缺省引入的包为 java.lang

    System.out.println("显示输出");  //不需要 import.java.lang.System
    ​
    //同包中的其他类不需要导入
    package com.yan;
    public class A{}
    ​
    package com.yan;
    public class B{
        public void pp(){
            A a = new A();   // 不需要  import.com.yan.A
        }
    }

  • 引入包中的类:import包名称.类名称;例如 import.java.Date;

  • 引入整个包:import 包名称.*;例如 import.java.util.*;

  • 不引入包而是用类,则需要用类的全名:包名.类名,例如 java.util.Date dd = new java.util.Date();

范围限定词和包

//定义不包含再其他类的外部类时,class前的范围限定词可以使用public或者默认
//public 到处可见  没有限定词只能同包访问
​
package com.yau;
public class A{
    public static void main(String[] args){
        B b = new B();
    }
}
class B{}
​
​
package com.yau1;
public class C{
    public static void main(String[] args){
        B b1 = new B();  //语法错误  默认类B是默认class  只能同包访问
    }
}
​
//成员属性和成员方法:定义在class内部,除了构造器(匿名内部代码块)和析构器之外的其他内容
public class A{
    public A{}  //方法名和类名一致,包括大小写,而且没有返回值类型声明---构造器
    //构造器方法不能直接调用,只能通过new运算符进行间接调用new A()系统自动执行A()方法
    
    public int A(){}  //语法正确,但是不是构造器,可以直接调用,new A().A()
    
    //成员方法
    public范围限定词  返回数据类型  方法名称 (参数类型1 形参名称1,...){
        //如果没有返回值类型为void
        return xxx;   返回值类型和返回类型声明一致;如果返回类型为void则return后面不能带任何数据
    }   //成员方法的调用为   对象名.方法名称(实际参数列表)
}

包文件组织和类路径CLASSPATH

在类路径中定义包的位置

  • 代表当前目录,为默认值

  • 类文件存放的位置:类路径中的目录\包名称对应的路径

  • 缺省包default package

  • 源文件代码中没有package语句声明,且类文件位于CLASSPATH所定义的目录中

  • 满足以上条件的所有类被认为在同一个包中,这个包被称为缺省包

Classpath描述了Java虚拟机在运行一个Class时在哪些路径中加载要运行的类以及运行的类要用到的类

当一个程序找不到它所需的其他文件时,系统会自动到CLASSPATH环境变量所指明的路径中去查找第三方提供的类和用户定义的类

Java中常用的包

  • java.applet用于提供Applet开发的支持,目前已经被flash所替代,很少使用,只有在某些地图系统中还使用

  • java.awt和java.swing用于单机软件或者c/s应用中的界面开发

  • java.io用于输入、输出操作

  • java.lang语言包,默认自动加载的包

  • java.net用于网络编程

  • java.util工具包,是Java提供的一些工具类

基础练习

面向对象的程序是由对象组成的,每个对象包含对用户公开的特定功能部分和隐藏的实现部分。在面向对象程序设计中,不必关心对象的具体实现。在传统的结构化程序设计中,算法是第一位的,数据结构是第二位的,即首先确定如何操作数,再去考虑如何组织数据,以方便操作。而OOP则颠倒了这种次序,将数据放在第一位,然后再考虑操作数据的算法。

抽象

忽略掉一个对象或实体的细节而只关注其本质特征的过程,可以简化功能与格式,帮助用户与对象交互是人类解决问题的基本法宝。良好的抽象策略可以控制问题的复杂程度,增强系统的通用性和可扩展性

抽象主要包括过程抽象和数据抽象

  • 过程抽象是将问题域中具有明确功能定义的操作抽取出来,并将其作为一个实体看待

  • 数据抽象是较过程抽象更高级别的抽象方式,将描述客体的属性和行为绑定在一起,实现统一的抽象,从而达到对现实世界客体的真正模拟

类是构造对象的模板和蓝图。通俗的说,类相当于建筑的图纸,而对象相当于建筑物。由类构造对象的过程称为为创建对象的实例。Java中通过关键字class定义类,后跟类名

设计与编写类的过程实际上是一个实体共有属性和行为的一个抽象的过程

例如面对的是一个具体个体:学生,为了严爵对象存储在计算机中,所以定义了一个新的数据类型Student

class Student{}

分析问题域相关的属性:

class Student{
    private Long id;  //如果使用包装类,则默认值为null
    private String username = "小王";
    private int age;  //如果使用简单类型,则默认数值默认为0,布尔类型为false
}

分析问题域相关的行为---方法

class Student{
    public void study(){}
    public void sleep(){}
    
    private Long id;
    private String name = "小王";
    private int age;
}

定义类的目的就是为了在计算机中存储特定的对象,所以需要创建对应的对象,创建方法和简单类型中定义变量的含义一致

Student s1 = new Student();
s1.方法名();  //调用成员方法
​
new Student().sleep();

面向对象的编程可以认为是面向类的编程。编写类的过程,相当于我们定义了一种新的数据类型。

对象编程的核心是面向抽象编程,面向抽象编程的核心是面向接口编程

字段和方法

定义一个类是,可以在类里设置两种类型的元素:数据成员和成员函数。其中数据成员是一种对象,可以是任何类型。如果是指向对象的句柄,则必须初始化这个句柄,通过构造器与一个实际对象连接起来。

如果是基本数据类型,则可以在类定义的位置直接初始化

public class Student{
    private int age;  //属性在不赋值时会有默认值
    private String username;
    private Course[] course;
}
public class Course{
    
}

引用和指针的区别:

引用也叫句柄,类似与指针,但是和指针是不同的。指针是一个存放地址的变量,是程序员可以灵活的访问内存,有可以对指针进行任意的运算操作,所以给程序带来了安全隐患和意想不到的结果。引用继承了指针节省内存的优点,但是限制了对地址的操作,他是安全的。Java种所有的变量都是一个引用,Java中没有指针的概念

每个对象都为自己的数据成员保有存储空间;数据成员不会在对象之间共享。

通过关键字new来创建一个对象

成员变量和局部变量的区别

成员变量定义在类中,整个类都可以访问

class Student{
    private String username;  //定义在类中的所有方法之外,在整个类体的范围内有效,和具体的位置无关
}

局部变量定义在方法、语句、局部代码块中,只在所属的区域中有效,而且必须是先定义后使用,先赋值后使用

public static void pp(){
    int kk = 100;  //局部变量
    for(i = 0;;){}  //局部变量
}

成员变量存放在对内的对象中,堆内存中的对象大小可以任意,并允许在运行是进行调整。所以访问查找的效率比较低。

局部变量存在于栈内存的方法中,可以快速定位,但是大小是限定的

成员变量随着对象的创建而存在,随着对象的消失而消失。局部变量随着所属区域的执行而存在,随着所属区域的结束而释放

成员变量都有默认初始化值;局部变量没有默认初始化值

用句柄操作对象

尽管Java是完全面向对象的。但是,操作的标识符实际指向一个对象的句柄,又称为引用。句柄四可以独立存在的,并不是说,拥有一个句柄就必须有一个对象与之对应。比如,int i定义了一个整形变量i,并不表示它一定有值

在java中方法的调用形式为 对象名.方法名

方法

方法可以理解为一个命名的代码块,通过名称就可以重复使用这段代码,而不是反复书写,可以达到代码的重用的目的

  • 参数:是指进入方法中的数据,有了这些数据,方法才能执行逻辑

  • 返回值:是指从方法中出来的数据,也就是方法执行之后的最终结果数据

方法可以有参数,也可以没有参数;可以有返回值,也可以没有返回值

目前定义方法的基本格式:

修饰符  返回值类型  方法名称(参数类型  参数名称){
    方法体
        return 返回值;
}
  • 修饰符

  • 返回值类型:方法最终产生的结果数据是什么类型

  • 方法名称:进入方法的数据是什么类型

  • 参数名称:进入方法的数据对应的变量名称

  • 方法体:方法内部执行的若干行代码

  • return:结束方法的执行,并且将返回值饭还给调用出

  • 返回值:方法最终产生的结果数据

注意:

  • 返回值必须和返回值类型对应

  • 参数如果有多个,需要使用都好分隔

  • 参数如果没有,小括号则可以留空

  • 多个方法定义的先后顺序无所谓

  • 不能在一个方法内部定义方法

  • 方法定义之后,没有调用就不会执行;想要执行,就一定调用它

参数传递

  • 形式参数:在定义方法的时候,写在小括号之内的变量就叫做形式参数。实际上方法定义中起到占位符的作用,会在方法调用的时候被传递过来的实际值所替代

  • 实际参数:在调用方法的时候,真正传入方法里的数据,叫做实际参数

圆括号中的实参列表为表用方法时实际传入的实际参数,称为实参列表。声明方法时圆括号中的擦书称为形式参数,形式参数和实际参数的个数和顺序必须一致,数据类型和个数上一定要匹配

注意:调用方法时形式参数和实际参数的个数和顺序必须一致,数据类型也必须相同。


  • return 123;表示返回结果为123,这个值返回到调用出。当然要求返回值的类型和声明的返回值类型一致

    public void pp(){
        return null;  //语法报错,返回值类型为void的方法体中,只能使用return;
    }

  • return; 表示从这里结束方法的执行,并返回调用出,但是没有具体的返回值。这里要求声明时的返回值类型为void

重名问题

  • 变量的名称可以和方法名称重名

  • 两个不同的方法体中,变量名可以重名

面向对象和面向过程的区别

面向过程

优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素

缺点:没有面向对象易维护、易复用、易扩展

面向对象:

优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活,更易于维护

缺点:性能比面向过程低

具体练习

1.猜数字游戏

public class GuessName{
    private int target = 0;
    private int[] history = new int[15];
    private int count;
    public GuessName(){
        target = (int)(Math.random()*100);
    }
    public boolean guess(int num){
        history[count++] = num;
        boolean res = false;
        if(num > target){
            System.out.println("你猜大了");
        }else if(num < target){
            System.out.println("你猜小了");
        }else{
            System.out.println("你猜对了");
            res = true;
        }
        return res;      
    }
    public static void main(String[] args){
        GuessName gg = new GuessName();
        Scanner sc = new Scanner(System.in);
        while(true){
            System.out.println("请输入整数:");
            int kk = sc.nextInt();
            boolean ret = gg.guess(kk);
            if(ret)
                break;
        }
        sc.close();
    }
}

2.计算圆的面积和周长,输入半径值

public class Yuan{
    private double radius;
    public Yuan(double r){
        radius = r;
    }
    public double getArea(){
        return Math.PI*radius*radius
    }
    public double getAround(){
        return 2*Math.PI*radius;
    }
    public static void main(String[] args){
        Yuan rr = new Yuan(3);
        System.out.println(rr.getArea());
        System.out.println(rr.getAround());
    }
}

3.请定义一个交通工具Vehicle的类,其中有:

属性:速度(speed),车的类型(type);方法:移动(move()),设置速度(setSpeed(double s)),加速speedUp(double s)。最后在测试类Vehicle中的main()中实例化一个交通工具对象,并通过构造方法给它初始化speed,type的值,并且打印出来。另外,调用加速,减速的方法对速度进行改变

public class Vehicle {
    private int speed;
    private String type;
    public int getSpeed() {
        return speed;
    }
    public void setSpeed(int speed) {
        this.speed = speed;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public void speedUp(double s) {
        speed += s;
    }
    public void speedDown(double s) {
        speed -= s;
        if(speed < 0)
            speed = 0;
    }
    public void setSpeed(double s) {
        speed = (int)s;
    }
​
}
​
public class VehicleTest {
    public static void main(String[] args) {
        Vehicle pp = new Vehicle();
        pp.setSpeed(100);
        pp.setType("跑车");
        System.out.println(pp.getSpeed());
        System.out.println(pp.getType());
        pp.speedUp(20);
        pp.speedDown(30);
        System.out.println(pp.getSpeed());
    }
​
}

4.利用继承来描述人,老师,学生之间的关系

(1)老师含有属性:name、age、subject;含有方法:eat、teach、toString

(2)学生含有属性:name,age,class,含有的方法:eat,study,toString

(3)利用继承思想,从老师和学生中抽出人,并创建Test进行调用并输出(System.out)

toString方法:toString() 方法返回此对象本身(它已经是一个字符串)。

package snippet;
​
public class The {
​
}
​
class Teacher {
    private String name;
    private int age;
    private String subject;
​
    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 getSubject() {
        return subject;
    }
​
    public void setSubject(String subject) {
        this.subject = subject;
    }
​
    public void eat() {
        System.out.println("教师吃饭!");
    }
​
    public void teach() {
        System.out.println("教师教学!");
    }
​
    public String toString() {
        return "姓名:" + this.name + " " + "年龄:" + this.age;
​
    }
}
​
class Student extends Teacher {
    private String class1;
​
    public String getClass1() {
        return class1;
    }
​
    public void setClass1(String class1) {
        this.class1 = class1;
    }
​
    public void eat() {
        System.out.println("学生吃饭!");
    }
​
    public void study() {
        System.out.println("学生学习!");
    }
​
}
//测试类Test
package snippet;
​
public class TheTest {
    public static void main(String[] args) {
        Teacher tea = new Teacher();
        tea.setName("教师");
        tea.setAge(35);
        tea.eat();
        tea.teach();
        System.out.println(tea.toString());
        System.out.println("===========");
        Student stu = new Student();
        stu.setName("学生");
        stu.setAge(18);
        System.out.println(stu.toString());
        stu.eat();
        stu.study();
​
    }
​
}

运行结果为:

5.定义一个类Calculate1,实现如加、减两种运算,然后编写一个派生类Calculate2,实现乘除两种运算

public class Calculate1 {
    private double num1;
    private double num2;
​
    public double add() {
        return num1 + num2;
    }
​
    public double sub() {
        return num1 - num2;
    }
​
    public double getNum1() {
        return num1;
    }
​
    public void setNum1(double num1) {
        this.num1 = num1;
    }
​
    public double getNum2() {
        return num2;
    }
​
    public void setNum2(double num2) {
        this.num2 = num2;
    }
​
}
//==============
public class Calculate2 extends Calculate1 {
    public double multiple() {
        return this.getNum1() * this.getNum2();
    }
​
    public double division() {
        return this.getNum1() / this.getNum2();
    }
​
    public static void main(String[] args) {
        Calculate2 obj = new Calculate2();
        obj.setNum1(10.0);
        obj.setNum2(20.0);
        System.out.println(obj.add());
        System.out.println(obj.sub());
        System.out.println(obj.multiple());
        System.out.println(obj.division());
    }
}

构造器方法

构造函数是一种特殊的方法,不算是成员方法。主要用来在创建对象是初始化对象,即为对象成员变量赋初始值,总于new运算符一起使用在创建对象的语句中。

public class A{
    public A(){ //不能有返回值类型,甚至void都不允许出现        
    }
    public A(int k){}
    public A(String name){}
    public A(int k,Strin name){}
}

一个类可以有多个构造器,可以根据其参数个数不同或参数类型的不同来区分他们,即构造函数重载

new A();  对应的构造器为A(){}
new A(100);  对应的构造器为A(int k){}
new A(true);  对应的构造器为A(Boolean kk){}

不算成员方法

构造器的特点

  • 函数名于类名相同,包括大小写

  • 不用定义返回值类型,不用写void。不能return具体指,可以使用return没有返回值

  • 没有具体的返回值

  • 一个类可以有多个不同的构造器,但是参数一定不能相同

    • Java中并不识别参数名称

  • 在构造函数面前加上返回值就是一般函数了

构造器作用

构造器用于给对象进行初始化,可创建对象new构造函数();

public class A{
    private int age;
    private String name;
    //出现了2个同名的name变量,一个是成员变量,一个是局部变量,用this进行区分,this.name标识成员变量,直接使用name表示局部变量
    
    public A(int age,String name){
        this.name = name;
        this.age = age;
        System.out.println(name);//按照就近原则,这个name用于取代局部变量
    }
}

当使用new运算符时进行调用,但是构造方法不能直接调用

  • 关键字new通常称为创建运算符

  • 一旦new 完成分配和初始化内存,它将调用构造函数来执行对象初始化

当定义Java类时没有定义构造器,则Java自动为类提供无参构造器,将成员变量的值初始化为缺省值

  • 简单类型属性:数值为0,boolean为false,char为\u0000

  • 复杂类型属性:null

一旦创建了自己的构造函数,缺省的构造函数即将不复存在

创建对象都必须通过构造函数初始化

每个类至少有一个构造方法

  • 一个类中如果没有定义过构造函数,那么该类中会有一个默认的空参数构造函数

  • 如果类中定义了指定的构造函数,那么类中的默认构造函数就没有了

金尽量不要在类的构造器中创建、初始化大量或执行某种复杂、耗时的运算逻辑

一般函数和构造函数的区别

构造函数:对象创建时,就会调用与之对应的构造函数,对对象进行初始化 new A()

一般函数:对象创建后,需要函数功能时才调用

构造函数:对象创建时,会调用并且只调用一次

一般函数:对象创建后,可以被多次调用

析构器

析构方法--析构器--在垃圾回收之前运行的方法--资源回收

由于垃圾回收的执行实际不确定,而且不能保证一定会执行析构器,多以一般不能使用析构方法执行资源回收

finalize()方法无法保证一定会执行,jdk10+已放弃用此方法

总结继承

继承就是在已经存在的类的基础上进行扩展,从而产生新的类,支持了层次结构分类的概念。已经存在的类称为父类,超类或基类,而新产生的类称为子类或者派生类。多个类中存在相同的属性或者行为时,将这些内容抽取到单独一个类中,那么多个类无需在定义这些属性和行为,只要继承那个类即可。多个类可以称为子类,单独这个类称为父类或者超类

  • 通过extends关键字让类于类之间产生继承关系

    • 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为

    • 继承是使用一存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也就是用父类的功能,但是不能选择性的继承

    • 继承就是is--a的关系

  • 在java中父类所拥有的一切,子类都可以继承

    • 私有属性是否可以被继承---两种答案

    • 子类除了拥有父类的属性和方法(永远有父类的所有成员,但是注意构造器和析构器不是成员),也可以创建自己的特性

    • 可以减少代码,而且易于维护

  • 建议使用的场景:把通过操作和方法放在父类 种,将特殊的方法定义在子类种。好处在于:1、避免代码重复 2、避免了认为因素导致的不一致性

继承的特性

1、java中不支持多重继承。Java中要求任何的子类只能有一个直系的双亲类

原因:因为击沉容易出现问题。两个父类中有相同的方法,子类到底要执行哪一个是不确定的

2、如果定义类但是没有extends,则意味这默认父类java.lang.Object。这也就是说Java中的任意类都是Object的子类

3、可以在子类中进行覆盖定义父类中的成员方法和成员属性

public A{
    private Long id;
}
​
public B extends A{
    private String id;
}

Java支持多层继承(继承体系):Java中的所有类都直接或者间接的继承于java.lang.Object类

C继承B,B继承A,就会出现继承体系

多层继承出现的继承体系中,通常看父类的功能,了解该体系的基本功能,建立子类对象,即可使用该体系功能定义继承需要注意:不要仅为了获取其他类中的某个功能而去继承,类鱼类之间要有所属(is --- a)关系

继承的优点

继承的出现提高了代码的复用性。继承的出现然类于类之间产生了关系,提供了多态的前提

  • 将所有子类的共同属性放入父类,实现代码共享,避免重复,提高开发效率

  • 可以使得修改扩展击沉而来的实现比较简单

继承的缺陷

父类变,子类就必须变

继承破坏了封装,对于父类而言,它的是实现细节对于子类来说都是透明的

继承是一种强耦合关系

继承的编码问题

public class Person{
    public Person(){
        System.out.println("Person...");
    }
}
public class Student extends Person{
    public Student(){
        System.out.println("Student...");
    }
    public static void main(String[] args){
        Student s1 = new Student();
    }
}

结论:上述流程中先查找所有的父类,然后才从根类开始著层层调用构造器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值