面向对象

今日内容介绍

u 构造方法

u this

u super

第1章 构造方法

我们对封装已经有了基本的了解,接下来我们来看一个新的问题,依然以Person为例,由于Person中的属性都被private了,外界无法直接访问属性,必须对外提供相应的set和get方法。当创建人对象的时候,人对象一创建就要明确其姓名和年龄,那该怎么做呢?

1.1 构造方法介绍

在开发中经常需要在创建对象的同时明确对象的属性值,比如员工入职公司就要明确他的姓名、年龄等属性信息。

那么,创建对象就要明确属性值,那怎么解决呢?也就是在创建对象的时候就要做的事情,当使用new关键字创建对象时,怎么给对象的属性初始化值呢?这就要学习Java另外一门小技术,构造方法。

那什么是构造方法呢?从字面上理解即为构建创造时用的方法,即就是对象创建时要执行的方法。既然是对象创建时要执行的方法,那么只要在new对象时,知道其执行的构造方法是什么,就可以在执行这个方法的时候给对象进行属性赋值。

l 构造方法的格式:

修饰符 构造方法名(参数列表)

{

}

l 构造方法的体现:

l 构造方法没有返回值类型。也不需要写返回值。因为它是为构建对象的,对象创建完,方法就执行结束。

l 构造方法名称必须和类型保持一致。

l 构造方法没有具体的返回值。

l 构造方法的代码体现:

class Person {

// Person的成员属性age和name

private int age;

private String name;

// Person的构造方法,拥有参数列表

Person(int a, String nm) {

// 接受到创建对象时传递进来的值,将值赋给成员属性

age = a;

name = nm;

}

}

1.2 构造方法调用和内存图解

理解构造方法的格式和基本功能之后,现在就要研究构造方法是怎么执行的呢?在创建对象的时候是如何初始化的呢?

构造方法是专门用来创建对象的,也就是在new对象时要调用构造方法。现在来看看如何调用构造方法。

class Person {

// Person的成员属性age和name

private int age;

private String name;

// Person的构造方法,拥有参数列表

Person(int a, String nm) {

// 接受到创建对象时传递进来的值,将值赋给成员属性

age = a;

name = nm;

}

public void speak() {

System.out.println("name=" + name + ",age=" + age);

}

}

class PersonDemo {

public static void main(String[] args) {

// 创建Person对象,并明确对象的年龄和姓名

Person p2 = new Person(23, "张三");

p2.speak();

}

}

上述代码演示了创建对象时构造方法的调用。即在创建对象时,会调用与参数列表对应的构造方法。

上述代码的图解:

l 图解说明:

1、首先会将main方法压入栈中,执行main方法中的 new Person(23,"张三");

2、在堆内存中分配一片区域,用来存放创建的Person对象,这片内存区域会有属于自己的内存地址(0x88)。然后给成员变量进行默认初始化(name=null,age=0)。

3、执行构造方法中的代码(age = a ; name = nm;),将变量a对应的23赋值给age,将变量nm对应的”张三赋值给name,这段代码执行结束后,成员变量age和name的值已经改变。执行结束之后构造方法弹栈,Person对象创建完成。将Person对象的内存地址0x88赋值给p2。

1.3 默认构造方法和细节

在没有学习构造方法之前,我们也可以通过new关键字创建对象,并调用相应的方法,同时在描述事物时也没有写构造方法。这是为什么呢?

在之前学习的过程中,描述事物时,并没有显示指定构造方法,当在编译Java文件时,编译器会自动给class文件中添加默认的构造方法。如果在描述类时,我们显示指定了构造方法,那么,当在编译Java源文件时,编译器就不会再给class文件中添加默认构造方法。

class  Person {

//如果没有显示指定构造方法,编译会在编译时自动添加默认的构造方法

//Person(){}  //空参数的默认构造方法

}

当在描述事物时,要不要在类中写构造方法呢?这时要根据描述事物的特点来确定,当描述的事物在创建其对象时就要明确属性的值,这时就需要在定义类的时候书写带参数的构造方法。若创建对象时不需要明确具体的数据,这时可以不用书写构造方法(不书写也有默认的构造方法)。

l 构造方法的细节:

1、一个类中可以有多个构造方法,多个构造方法是以重载的形式存在的

2、构造方法是可以被private修饰的,作用:其他程序无法创建该类的对象。

class Person {

private int age;

private String name;

// 私有无参数的构造方法,即外界不能通过new Person();语句创建本类对象

private Person() {

}

// 多个构造方法是以重载的形式存在

Person(int a) {

age = a;

}

Person(String nm, int a) {

name = nm;

age = a;

}

}

1.4 构造方法和一般方法区别

到目前为止,学习两种方法,分别为构造方法和一般方法,那么他们之间有什么异同呢?

构造方法在对象创建时就执行了,而且只执行一次。

一般方法是在对象创建后,需要使用时才被对象调用,并可以被多次调用。

l 问题:

有了构造方法之后可以对对象的属性进行初始化,那么还需要对应的set和get方法吗?

需要相应的set和get方法,因为对象在创建之后需要修改和访问相应的属性值时,在这时只能通过set或者get方法来操作。

思考,如下代码有问题吗?

class Person {

void Person() {

}

}

class PersonDemo {

public static void main(String[] args) {

Person p = new Person();

}

}

第2章 this关键字

在之前学习方法时,我们知道方法之间是可以相互调用的,那么构造方法之间能不能相互调用呢?若可以,怎么调用呢?

2.1 this调用构造方法

在之前学习方法之间调用时,可以通过方法名进行调用。可是针对构造方法,无法通过构造方法名来相互调用。

构造方法之间的调用,可以通过this关键字来完成。

l 构造方法调用格式:

this(参数列表);

l 构造方法的调用

class Person {

// Person的成员属性

private int age;

private String name;

// 无参数的构造方法

Person() {

}

// 给姓名初始化的构造方法

Person(String nm) {

name = nm;

}

// 给姓名和年龄初始化的构造方法

Person(String nm, int a) {

// 由于已经存在给姓名进行初始化的构造方法 name = nm;因此只需要调用即可

// 调用其他构造方法,需要通过this关键字来调用

this(nm);

// 给年龄初始化

age = a;

}

}

2.2 this的原理图解

了解了构造方法之间是可以相互调用,那为什么他们之间通过this就可以调用呢?

通过上面的学习,简单知道使用this可以实现构造方法之间的调用,但是为什么就会知道this调用哪一个构造方法呢?接下来需要图解完成。

class Person {

private int age;

private String name;

Person() {

}

Person(String nm) {

name = nm;

}

Person(String nm, int a) {

this(nm);

age = a;

}

}

class PersonDemo {

public static void main(String[] args) {

Person p = new Person("张三", 23);

}

}

l 图列说明:

1、先执行main方法,main方法压栈,执行其中的new Person(“张三”,23);

2、堆内存中开辟空间,并为其分配内存地址0x33,,紧接着成员变量默认初始化(name=null  age = 0);

3、拥有两个参数的构造方法(Person(String nm , int a))压栈,在这个构造方法中有一个隐式的this,因为构造方法是给对象初始化的,那个对象调用到这个构造方法,this就指向堆中的那个对象。

4、由于Person(String nm , int a)构造方法中使用了this(nm);构造方法Person(String nm)就会压栈,并将“张三”传递给nm。在Person(String nm , int a)构造方法中同样也有隐式的this,this的值同样也为0x33,这时会执行其中name = nm,即把“张三”赋值给成员的name。当赋值结束后Person(String nm , int a)构造方法弹栈。

5、程序继续执行构造方法(Person(String nm , int a)中的age = a;这时会将23赋值给成员属性age。赋值结束构造方法(Person(String nm , int a)弹栈。

6、当构造方法(Person(String nm , int a)弹栈结束后,Person对象在内存中创建完成,并将0x33赋值给main方法中的p引用变量。

l 注意:

this到底代表什么呢?this代表的是对象,具体代表哪个对象呢?哪个对象调用了this所在的方法,this就代表哪个对象。

调用其他构造方法的语句必须定义在构造方法的第一行,原因是初始化动作要最先执行。

2.3 成员变量和局部变量同名问题

通过上面学习,基本明确了对象初始化过程中的细节,也知道了构造方法之间的调用是通过this关键字完成的。但this也有另外一个用途,接下来我们就学习下。

当在方法中出现了局部变量和成员变量同名的时候,那么在方法中怎么区别局部变量成员变量呢?可以在成员变量名前面加上this.来区别成员变量和局部变量

class Person {

private int age;

private String name;

// 给姓名和年龄初始化的构造方法

Person(String name, int age) {

// 当需要访问成员变量是,只需要在成员变量前面加上this.即可

this.name = name;

this.age = age;

}

public void speak() {

System.out.println("name=" + this.name + ",age=" + this.age);

}

}

class PersonDemo {

public static void main(String[] args) {

Person p = new Person("张三", 23);

p.speak();

}

}

2.4 this的应用

学习完了构造方法、this的用法之后,现在做个小小的练习。

需求:在Person类中定义功能,判断两个人是否是同龄人

class Person {

private int age;

private String name;

// 给姓名和年龄初始化的构造方法

Person(String name, int age) {

// 当需要访问成员变量是,只需要在成员变量前面加上this.即可

this.name = name;

this.age = age;

}

public void speak() {

System.out.println("name=" + this.name + ",age=" + this.age);

}

// 判断是否为同龄人

public boolean equalsAge(Person p) {

// 使用当前调用该equalsAge方法对象的age和传递进来p的age进行比较

// 由于无法确定具体是哪一个对象调用equalsAge方法,这里就可以使用this来代替

/*

* if(this.age == p.age) { return true; } return false;

*/

return this.age = p.age;

}

}

第3章 super关键字

3.1 子父类中构造方法的调用

在创建子类对象时,父类的构造方法会先执行,因为子类中所有构造方法的第一行有默认的隐式super();语句。

格式:

调用本类中的构造方法

this(实参列表);

调用父类中的空参数构造方法

super();

调用父类中的有参数构造方法

super(实参列表);

为什么子类对象创建都要访问父类中的构造方法?因为子类继承了父类的内容,所以创建对象时,必须要先看父类是如何对其内容进行初始化的,看如下程序:

public class Test {

public static void main(String[] args) {

new Zi();

}

}

class Fu{

int num ;

Fu(){

System.out.println("Fu构造方法"+num);

num = 4;

}

}

class Zi extends Fu{

Zi(){

//super(); 调用父类空参数构造方法

System.out.println("Zi构造方法"+num);

}

}

  执行结果:

       Fu构造方法0

       Zi构造方法4

通过结果发现,子类构造方法执行时中,调用了父类构造方法,这说明,子类构造方法中有一句super()。

那么,子类中的构造方法为什么会有一句隐式的super()呢?

原因:子类会继承父类中的内容,所以子类在初始化时,必须先到父类中去执行父类的初始化动作。这样,才可以使用父类中的内容。

当父类中没有空参数构造方法时,子类的构造方法必须有显示的super语句,指定要访问的父类有参数构造方法。

3.2 子类对象创建过程的细节

如果子类的构造方法第一行写了this调用了本类其他构造方法,那么super调用父类的语句还有吗?

这时是没有的,因为this()或者super(),只能定义在构造方法的第一行,因为初始化动作要先执行。

父类构造方法中是否有隐式的super呢?

也是有的。记住:只要是构造方法默认第一行都是super();

父类的父类是谁呢?super调用的到底是谁的构造方法呢?

Java体系在设计,定义了一个所有对象的父类Object

l 注意:

类中的构造方法默认第一行都有隐式的super()语句,在访问父类中的空参数构造方法。所以父类的构造方法既可以给自己的对象初始化,也可以给自己的子类对象初始化。

如果默认的隐式super()语句在父类中没有对应的构造方法,那么必须在构造方法中通过this或者super的形式明确要调用的构造方法。

3.3 super应用

练习:描述学生和工人这两个类,将他们的共性name和age抽取出来存放在父类中,并提供相应的get和set方法,同时需要在创建学生和工人对象就必须明确姓名和年龄

//定义Person类,将Student和Worker共性抽取出来

class Person {

private String name;

private int age;

public Person(String name, int age) {

// super();

this.name = name;

this.age = age;

}

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;

}

}

class Student extends Person {

// Student类的构造方法

Student(String name, int age) {

// 使用super关键字调用父类构造方法,进行相应的初始化动作

super(name, age);

}

public void study() {// Studnet中特有的方法

System.out.println(this.getName() + "同学在学习");

}

}

class Worker extends Person {

Worker(String name, int age) {

// 使用super关键字调用父类构造方法,进行相应的初始化动作

super(name, age);

}

public void work() {// Worker 中特有的方法

System.out.println(this.getName() + "工人在工作");

}

}

public class Test {

public static void main(String[] args) {

Student stu = new Student("小明",23);

stu.study();

Worker w = new Worker("小李",45);

w.work();

}

}

第4章 综合案例---完整的员工类

4.1 案例介绍

某IT公司有多名员工,按照员工负责的工作不同,进行了部门的划分(研发部员工、维护部员工)。研发部根据所需研发的内容不同,又分为JavaEE工程师、Android工程师;维护部根据所需维护的内容不同,又分为网络维护工程师、硬件维护工程师。

公司的每名员工都有他们自己的员工编号、姓名,并要做它们所负责的工作。

l 工作内容

l JavaEE工程师:员工号为xxx的 xxx员工,正在研发淘宝网站

l Android工程师:员工号为xxx的 xxx员工,正在研发淘宝手机客户端软件

l 网络维护工程师:员工号为xxx的 xxx员工,正在检查网络是否畅通

l 硬件维护工程师:员工号为xxx的 xxx员工,正在修复打印机

请根据描述,完成员工体系中所有类的定义,并指定类之间的继承关系。进行XX工程师类的对象创建,完成工作方法的调用。

4.2 案例分析

l 根据上述部门的描述,得出如下的员工体系图

l 根据员工信息的描述,确定每个员工都有员工编号、姓名、要进行工作。则,把这些共同的属性与功能抽取到父类中(员工类),关于工作的内容由具体的工程师来进行指定。

l 工作内容

l JavaEE工程师:员工号为xxx的 xxx员工,正在研发淘宝网站

l Android工程师:员工号为xxx的 xxx员工,正在研发淘宝手机客户端软件

l 网络维护工程师:员工号为xxx的 xxx员工,正在检查网络是否畅通

l 硬件维护工程师:员工号为xxx的 xxx员工,正在修复打印机

l 创建JavaEE工程师对象,完成工作方法的调用

4.3 案例代码实现

l 根据员工体系图,完成类的定义

定义员工类(抽象类)

public abstract class Employee {

private String id;// 员工编号

private String name; // 员工姓名

//空参数构造方法

public Employee() {

super();

}

//有参数构造方法

public Employee(String id, String name) {

super();

this.id = id;

this.name = name;

}

public String getId() {

return id;

}

public void setId(String id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

//工作方法(抽象方法)

public abstract void work();

}

l 定义研发部员工类Developer 继承 员工类Employee

public abstract class Developer extends Employee {

//空参数构造方法

public Developer() {

super();

}

//有参数构造方法

public Developer(String id, String name) {

super(id, name);

}

}

l 定义维护部员工类Maintainer 继承 员工类Employee

public abstract class Maintainer extends Employee {

//空参数构造方法

public Maintainer() {

super();

}

//有参数构造方法

public Maintainer(String id, String name) {

super(id, name);

}

}

l 定义JavaEE工程师 继承 研发部员工类,重写工作方法

public class JavaEE extends Developer {

//空参数构造方法

public JavaEE() {

super();

}

//有参数构造方法

public JavaEE(String id, String name) {

super(id, name);

}

@Override

public void work() {

System.out.println("员工号为 " + getId() + " 的 " + getName() + " 员工,正在研发淘宝网站");

}

}

l 定义Android工程师 继承 研发部员工类,重写工作方法

public class Android extends Developer {

//空参数构造方法

public Android() {

super();

}

//有参数构造方法

public Android(String id, String name) {

super(id, name);

}

@Override

public void work() {

System.out.println("员工号为 " + getId() + " 的 " + getName() + " 员工,正在研发淘宝手机客户端软件");

}

}

l 定义Network网络维护工程师 继承 维护部员工类,重写工作方法

public class Network extends Maintainer {

//空参数构造方法

public Network() {

super();

}

//有参数构造方法

public Network(String id, String name) {

super(id, name);

}

@Override

public void work() {

System.out.println("员工号为 " + getId() + " 的 " + getName() + " 员工,正在检查网络是否畅通");

}

}

l 定义Hardware硬件维护工程师 继承 维护部员工类,重写工作方法

public class Hardware extends Maintainer {

//空参数构造方法

public Hardware() {

super();

}

//有参数构造方法

public Hardware(String id, String name) {

super(id, name);

}

@Override

public void work() {

System.out.println("员工号为 " + getId() + " 的 " + getName() + " 员工,正在修复打印机");

}

}

l 在测试类中,创建JavaEE工程师对象,完成工作方法的调用

public class Test {

public static void main(String[] args) {

//创建JavaEE工程师员工对象,该员工的编号000015,员工的姓名 小明

JavaEE ee = new JavaEE("000015", "小明");

//调用该员工的工作方法

ee.work();

}

}

第5章 总结

5.1 知识点总结

l this关键字

l this关键字,本类对象的引用

l this是在方法中使用的,哪个对象调用了该方法,那么,this就代表调用该方法的对象引用

l this什么时候存在的?当创建对象的时候,this存在的

l this的作用:用来区别同名的成员变量与局部变量(this.成员变量)

public void setName(String name) {

this.name = name;

}

l 构造方法: 用来给类的成员进行初始化操作

l 格式:

修饰符 类名 (参数列表) {

...

}

l 构造方法的特点:

l 1, 方法名与类名相同

l 2,没有返回值,也没有返回值类型,连void也没有

l 构造方法什么时候会被调用执行?

只有在创建对象的时候才可以被调用

l super: 指的是父类的存储空间(理解为父类的引用)

调用父类的成员变量:

super.成员变量;

调用父类的构造方法:

super(参数);

调用方法的成员方法:

super.成员方法();

l 继承中的构造方法注意事项:

1,如果我们手动给出了构造方法,编译器不会在给我们提供默认的空参数构造方法

如果我们没写任何的构造方法,编译器提供给我们一个空参数构造方法

2, 在构造方法中,默认的第一条语句为 super();

它是用来访问父类中的空参数构造方法,进行父类成员的初始化操作

3, 当父类中没有空参数构造方法的时候,怎么办?

a: 通过 super(参数) 访问父类有参数的构造方法

b: 通过 this(参数) 访问本类中其他构造方法

注意:[本类中的其他构造方法已经能够正常访问父类构造方法]

4, super(参数) 与 this(参数) 不能同时在构造方法中存在

Java面向对象(构造方法、this、super)的更多相关文章

  1. Java面向对象-构造方法,this关键字

    Java面向对象-构造方法,this关键字 构造方法 概念:构造方法是一个特殊的方法,这个特殊方法用于创建实例时执行初始化操作: 上代码: package com.java1234.chap03.se ...

  2. Java—面向对象—构造方法及相关思维导图

    先构造一个Book类的代码 package org.hanqi.pn0120; public class Book { //构造方法 //1.方法名和类名一样 //2.没有返回值,不需要加void / ...

  3. JAVA面向对象-----构造方法

    我们人出生的时候,有些人一出生之后再起名字的,但是有些人一旦出生就已经起好名字的.那么我们在java里面怎么在对象一旦创建就赋值呢? 构造方法作用 构造方法作用:对对象进行初始化. 构造函数与普通的函 ...

  4. Java面向对象----继承概念,super关键字

    继承概念: 继承需要符合的关系  is-a  , 父类通用更抽象,子类更特殊更具体 类之间的关系 继承体现 组合体现 实现接口体现 继承的意义 代码重用 体现不同抽象层次 extends关键字 Sup ...

  5. Java面向对象之关键字super 入门实例

    一.基础概念 (一)super关键字 super关键字的用法和this相似.this代表的是当前对象.super代表的是父类中内存空间. 子父类中是不会出现同名属性的情况. (二)继承中.成员变量问题 ...

  6. JAVA面向对象-----super关键字

    JAVA面向对象-–super关键字 1:定义Father(父类)类 1:成员变量int x=1; 2:构造方法无参的和有参的,有输出语句 2:定义Son类extends Father类 1:成员变量 ...

  7. Java面向对象-Java类的继承及super关键字

    Java面向对象-Java类的继承 1,继承定义以及基本使用 定义:子类能够继承父类的属性和方法: 注意点:Java中只支持单继承: 私有方法不能继承: 上代码: package com.java12 ...

  8. JavaSE入门学习23:Java面向对象之构造方法

    学了JavaSE面向对象这一部分,也该对构造方法做一个总结了. 一构造方法 在多数情况下,初始化一个对象的终于步骤是去调用这个对象的构造方法. 构造方法负责对象的初始化工作,为 实例变量赋予合适的初始 ...

  9. 【Java基础】【07面向对象-构造方法&静态static】

    07.01_面向对象(构造方法Constructor概述和格式)(掌握) A:构造方法概述和作用 给对象的数据(属性)进行初始化 B:构造方法格式特点 a:方法名与类名相同(大小也要与类名一致) b: ...

随机推荐

  1. spring-data详解之spring-data-jpa:简单三步快速上手spring-data-jpa开发

    前言: 基于spring framework 4.x或spring boot 1.x开发环境 务必注意以下版本问题:Spring framework4.x(Spring boot1.x)对应sprin ...

  2. tyvj1124花店橱窗——有限制的DP

    题目:http://www.joyoi.cn/problem/tyvj-1124 此题首先注意一束花能往哪些花瓶中放置:原本应放在本位置,但因为有多余花瓶,故可以有些变动,范围在i~i+v-f间: 假 ...

  3. 洛谷P1352——动规

    题目:https://www.luogu.org/problemnew/show/P1352 代码如下: #include<iostream> #include<cstdio> ...

  4. 机器学习、图像识别方面 书籍推荐 via zhihu

    机器学习.图像识别方面 书籍推荐 作者:小涛 链接:https://www.zhihu.com/question/20523667/answer/97384340 来源:知乎 著作权归作者所有.商业转 ...

  5. python find()用法

    案例: ### 1 ### str = "01213456" if str.find("23"): print "YES!" else: p ...

  6. [Forward]Improving Web App Performance With the Chrome DevTools Timeline and Profiles

    Improving Web App Performance With the Chrome DevTools Timeline and Profiles We all want to create h ...

  7. Hibernate错误:javax/persistence/EntityListeners

    1. 原文地址:http://heavengate.blog.163.com/blog/static/20238105320127291018026/ 错误信息: hibernate:javax/pe ...

  8. function multi-versioning in GCC

    https://lwn.net/Articles/691932/ https://gcc.gnu.org/wiki/FunctionMultiVersioning why multi-versioni ...

  9. 《深入分析Java Web技术内幕》读后感(Tomcat)

    第11章 P286 Tomcat总体结构 1.service 2.server 3.组件的生命 Connector Container 1.容器的总体设计 2.Engine容器 3.Host容器 4. ...

  10. Linux之常用命令简析

    ls cd mkdir rmdir touch ln cp rm mv 1.ls   显示当前目录下的文件及文件夹(不显示隐藏的) -l   显示详细信息 --all  显示隐藏的文件及文件夹(就是显 ...