8_方法和封装

构造方法

  • 构造方法方法名与类名相同。
  • 没有返回值类型,连void都不允许有。
class 类名 {
    类名(形参列表) {
        构造方法体;
    }
}
public class Person {
    String name;
    int age;
    
    Person() {
        System.out.println("我是自定义的构造方法!");
    }
    
    void show() {
        System.out.println("我是" + name + ",今年" + age + "岁了。");
    }
    
    public static void main(String[] args) {
        Person p1 = new Person;
        p1.show();
    }
}

默认构造方法

  • 当一个类中没有定义任何构造方法时,编译器会自动添加一个无参空构造方法,叫做默认/缺省构造方法,如:Person(){}
  • 若类中出现了构造方法,则编译器不再提供任何形式的构造方法。
public class Person {
    String name;
    int age;
    
    Person(String s, int i) {
        name = s;
        age = i;
    }
    
    void show() {
        System.out.println("我是" + name + ",今年" + age + "岁了。");
    }
    
    public static void main(String[] args) {
        Person p1 = new Person("小仙女", 18);
        p1.show();
        
        Person p2 = new Person("大帅哥", 19);
        p2.show();
    }
}

构造方法的作用

  • 使用new关键字创建对象是会自动调用构造方法实现成员变量初始化工作。

重载的概念

  • 若方法名称相同,参数列表不同,这样的方法之间构成重载关系(Overlord)。
public class OverloadTest {
    void show() {
        System.out.println("show()");
    }
    void show(int i) {
        System.out.println("show(int)");
    }
    void show(int i, double d) {
        System.out.println("show(int, double)");
    }
    void show(int i, int j) {
        System.out.println("show(int, int)");
    }
    void show(double d, int i) {
        System.out.println("show(int, int)");
    }
    
    
    public static void main(String[] args) {
        OverloadTest ot = new OverloadTest();
        ot.show();
        ot.show(66, 3.14);
        ot.show(66, 118);
        ot.show(3.14, 66);
    }
}

重载的体现形式

  • 方法重载的主要形式体现在:参数的个数不同、参数的类型不同、番薯的顺序不同,与返回值类型和形参变量名无关,但建议返回值类型最好相同。
  • 判断方法能否构成重载的核心:调用方法时能否加以区分。

重载的实际意义

  • 方法重载的实际意义在于调用者只需要记住一个方法名就可以调用各种不同的版本,来实现各种不同的功能。如:java.io.PrintStream类中的println方法。

this的基本概念

  • 若在构造方法中出现了this关键字,则代表当前正在构造的对象。
  • 若在成员方法中出现了this关键字,则代表当前正在调用的对象。
  • this关键字本质上就是当前类类型的引用变量。
public class ThisTest {
    ThisTest() {
        System.out.println("构造方法中:this = " + this);
    }
    
    void show() {
        System.out.println("成员方法中:this = " + this);
    }
    
    public static void main(String[] args) {
        ThisTest tt = new ThisTest();
        tt.show();
        System.out.println("main方法中:tt = " + tt);
    }
}
public class Person {
    String name;
    int age;
    
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
        
    public static void main(String[] args) {
        Person p = new Person("王乃卉", 23);
        System.out.println(p.name);
        System.out.println(p.age);
    }
}

public class Person {
    String name;
    int age;
    
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    Person getPerson() { //自定义成员方法实现Person类型对象的获取并返回的行为
        return this;
    }
    
    void grow() {
        age++;
    }
    
    void grow(int age) {
        this.age += age
    }
    
    public static void main(String[] args) {
        Person p = new Person("王乃卉", 23);
        System.out.println(p.name);
        System.out.println(p.age);
    }
}
public class Boy {
    String name;
    
    Boy() {
        System.out.println("无参构造方法");
    }
    
    Boy(String name) {
        System.out.println("有参构造方法");
        this.name = name;
    }
    
    void show() {
        
    }
}

引用变量的注意事项

实例

/*
编程实现参数n的阶乘并返回,所谓阶乘就是从1累乘到n的结果。
*/

public class JieChengTest {
    
    int show(int n) {
        int num = 1;
        for(i = 1, i <= n; i++) {
            num *= i;
        }
        return num;
    }
    
    public static void main(String[] args) {
        JieChengTest jct = new JieChengTest();
        int res = jct.show(5);
        System.out.println("5的阶乘是:" + res);
    }
}

阶乘

/*
编程实现参数n的阶乘并返回,所谓阶乘就是从1累乘到n的结果。
*/

public class JieChengTest {
    
    int show(int n) {
        if(1 == n) {
            return 1;
        }
        return n*show(n-1);
    }
    
    public static void main(String[] args) {
        JieChengTest jct = new JieChengTest();
        int res = jct.show(5);
        System.out.println("5的阶乘是:" + res);
    }
}

递归方式的原理分析

注意事项

  • 使用递归必须有递归的规律以及退出条件
  • 使用递归必须使得问题简单化而不是复杂化。
  • 若递归影响到程序的执行性能,则使用递推取代之。

费氏数列

/*
编程实现费氏数列中第n项的数值并返回。
费氏数列:1 1 2 3 5 8 13 21
1 + 1 = 2
1 + 2 = 3
2 + 3 = 5
3 + 5 = 8
5 + 8 = 13
8 + 13 = 21
...
*/

package cn.itcast.day01.demo07;

import org.w3c.dom.ls.LSOutput;
import java.util.Scanner;

public class FeiTest {

    int show(int n) {
        if (1 == n || 2 == n) {
            return 1;
        }
        return show(n - 1) + show(n - 2);
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入n的值:");
        int n = sc.nextInt();
        FeiTest f = new FeiTest();
        int res = f.show(n);
        System.out.println("费氏数列中第" + n + "项的数值是:" + res);
    }
}

费氏数列的递推实现

当n的值太大时,递归的效率已经特别低了,所以这时不太适合使用递归方式计算,使用递推的方式更好。

/*
编程实现费氏数列中第n项的数值并返回。
费氏数列:1 1 2 3 5 8 13 21
1 + 1 = 2
1 + 2 = 3
2 + 3 = 5
3 + 5 = 8
5 + 8 = 13
8 + 13 = 21
...
*/

package cn.itcast.day01.demo07;

import java.util.Scanner;

public class FeiTest {

    int show(int n) {
        if (1 == n || 2 == n) {
            return 1;
        }
        return show(n - 1) + show(n - 2);
    }

    int show2(int n) {
        if (1 == n || 2 == n) {
            return 1;
        }
        int a = 1;
        int b = 1;
        for (int i = 0; i < n - 2; i++) {
            int c = a + b;
            a = b;
            b = c;
        }
        return b;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入n的值:");
        int n = sc.nextInt();
        FeiTest f = new FeiTest();
        int res = f.show2(n);
        System.out.println("费氏数列中第" + n + "项的数值是:" + res);
    }
}

代码的拆分实现

Fee.java

/*
编程实现费氏数列中第n项的数值并返回。
费氏数列:1 1 2 3 5 8 13 21
1 + 1 = 2
1 + 2 = 3
2 + 3 = 5
3 + 5 = 8
5 + 8 = 13
8 + 13 = 21
...
*/

package cn.itcast.day01.demo07;

public class Fee {
    int show(int n) {
        if (1 == n || 2 == n) {
            return 1;
        }
        return show(n - 1) + show(n - 2);
    }

    int show2(int n) {
        if (1 == n || 2 == n) {
            return 1;
        }
        int a = 1;
        int b = 1;
        for (int i = 0; i < n - 2; i++) {
            int c = a + b;
            a = b;
            b = c;
        }
        return b;
    }
}

FeeTest.java

package cn.itcast.day01.demo07;

import java.util.Scanner;

public class FeeTest {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入n的值:");
        int n = sc.nextInt();
        Fee f = new Fee();
        int res = f.show2(n);
        System.out.println("费氏数列中第" + n + "项的数值是:" + res);
    }
}

封装的概念

封装的实现流程

Student.java

package cn.itcast.day01.demo08;

public class Student {
    private int id;
    private String name;

    public Student(int id, String name) {
        setId(id);
        setName(name);
    }

    public void setId(int id) {
        if (id > 0) {
            this.id = id;
        }else {
            System.out.println("id不合理");
        }
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void show() {
        System.out.println("我叫" + this.name + ",我的id是" + this.id);
    }
}

StudentTest.java

package cn.itcast.day01.demo08;

public class StudentTest {
    public static void main(String[] args) {
        Student stu = new Student(100, "尊龙");
        System.out.println("我是" + stu.getName() + ",我的学号是" + stu.getId());
    }
}

实例

编程实现学生信息的录入和打印

Student.java

package cn.itcast.day01.demo09;

public class Student {
    private int id;
    private String name;

    public Student(int id, String name) {
        setId(id);
        setName(name);
    }

    public void setId(int id) {
        if (id > 0) {
            this.id = id;
        }else {
            System.out.println("id不合理");
        }
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void show() {
        System.out.println("我叫" + this.name + ",我的id是" + this.id);
    }
}

StudentTest.java

package cn.itcast.day01.demo09;

import java.util.Scanner;

public class StudentTest {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入学生人数:");
        int num = sc.nextInt();
        Student[] arr = new Student[num];

        for (int i = 0; i < num; i++) {
            int j = i + 1;
            System.out.print("请输入第" + j + "个学生的id:");
            int id = sc.nextInt();
            System.out.print("请输入第" + j + "个学生的姓名:");
            String name = sc.next();
            Student stu = new Student(id, name);
            arr[i] = stu;
        }

        for (int i = 0; i < num; i++) {
            arr[i].show();
        }
    }
}

执行结果:

请输入学生人数:3
请输入第1个学生的id:100
请输入第1个学生的姓名:zunlong
请输入第2个学生的id:101
请输入第2个学生的姓名:wanglihong
请输入第3个学生的id:102
请输入第3个学生的姓名:wangfei
我叫zunlong,我的id是100
我叫wanglihong,我的id是101
我叫wangfei,我的id是102

JavaBean的概念

实例

People.java

/*
 * 编程实现People类的封装
 * */

package cn.itcast.day01.demo10;

public class People {
    private String name;
    private int age;
    private String nationality;

    public People() {}

    public People(String name, int age, String nationality) {
        this.setName(name);
        this.setAge(age);
        this.setNationality(nationality);
    }

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

    public String getName() {
        return name;
    }

    public void setAge(int age) {
        if (age > 0 && age < 150) {
            this.age = age;
        } else {
            System.out.println("你设置的年龄不合理!");
        }
    }

    public int getAge() {
        return age;
    }

    public void setNationality(String nationality) {
        this.nationality = nationality;
    }

    public String getNationality() {
        return nationality;
    }

    public void show() {
        System.out.println("我叫" + getName() + ",今年" + getAge() + "岁了,我来自" + getNationality());
    }
}

PeopleTest.java

/*
* 编程实现People类的测试
* */

package cn.itcast.day01.demo10;

public class PeopleTest {
    public static void main(String[] args) {
        People p1 = new People("zhangfei", 30, "China");
        p1.show();
        People p2 = new People("guanyu", 35 "China");
        p2.show();
    }
}

内存结构

static关键字的基本概念

People.java

/*
 * 编程实现People类的封装
 * */

package cn.itcast.day01.demo10;

public class People {
    private String name;
    private int age;
    private static String nationality;

    public People() {}

    public People(String name, int age, String nationality) {
        this.setName(name);
        this.setAge(age);
        this.setNationality(nationality);
    }

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

    public String getName() {
        return name;
    }

    public void setAge(int age) {
        if (age > 0 && age < 150) {
            this.age = age;
        } else {
            System.out.println("你设置的年龄不合理!");
        }
    }

    public int getAge() {
        return age;
    }

    public void setNationality(String nationality) {
        this.nationality = nationality;
    }

    public String getNationality() {
        return nationality;
    }

    public void show() {
        System.out.println("我叫" + getName() + ",今年" + getAge() + "岁了,我来自" + getNationality());
    }
}

PeopleTest.java

/*
* 编程实现People类的测试
* */

package cn.itcast.day01.demo10;

public class PeopleTest {
    public static void main(String[] args) {
        People p1 = new People("尊龙", 61, "American");
        p1.show();
        People p2 = new People("王菲", 43, "China");
        p2.show();

        System.out.println("----------------------------");
        p1.nationality = "蜀国";
        System.out.println("第一个对象的国籍是:" + p1.nationality);
        System.out.println("第二个对象的国籍是:" + p2.nationality);

        People p3 = new People();
        System.out.println("第三个对象的国籍是:" + p3.nationality);
    }
}
我叫尊龙,今年61岁了,我来自American
我叫王菲,今年43岁了,我来自China
----------------------------
第一个对象的国籍是:蜀国
第二个对象的国籍是:蜀国
第三个对象的国籍是:蜀国

static关键字的使用方式

People.java

/*
 * 编程实现People类的封装
 * */

package cn.itcast.day01.demo10;

public class People {
    private String name;
    private int age;
    private static String nationality;

    public People() {
    }

    public People(String name, int age) {
        this.setName(name);
        this.setAge(age);
    }

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

    public String getName() {
        return name;
    }

    public void setAge(int age) {
        if (age > 0 && age < 150) {
            this.age = age;
        } else {
            System.out.println("你设置的年龄不合理!");
        }
    }

    public int getAge() {
        return age;
    }

    public void setNationality(String nationality) {
        People.nationality = nationality;
    }

    public String getNationality() {
        return nationality;
    }

    public void show() {
        System.out.println("我叫" + getName() + ",今年" + getAge() + "岁了,我来自" + getNationality());
    }
}

PeopleTest.java

/*
* 编程实现People类的测试
* */

package cn.itcast.day01.demo10;

public class PeopleTest {
    public static void main(String[] args) {
        People p1 = new People("赵云", 28);
        p1.show();
        People p2 = new People("关于", 35);
        p2.show();

        System.out.println("----------------------------");
        p1.setNationality("蜀国");
        System.out.println("第一个对象的国籍是:" + p1.getNationality());
        System.out.println("第二个对象的国籍是:" + p2.getNationality());

        People p3 = new People();
        System.out.println("第三个对象的国籍是:" + p3.getNationality());
    }
}

构造块和静态代码块

/*
 * 编程实现构造块和静态代码块的使用
 * */
package cn.itcast.day01.demo10;

public class BlockTest {
    // 当需要在执行构造方法体之前做一些准备工作时,则将准备工作的相关代码写在构造块中即可,比如:对成员变量进行的统一初始化操作
    static {
        System.out.println("####静态代码块####");
    }
    // 静态代码块会随着类的加载而准备就绪,会先于构造块执行
    // 当需要在执行代码块之前随着类的加载做一些准备工作时,则编写代码到静态代码块中,比如:加载数据库的驱动包等
    {
        System.out.println("####构造块####");
    }

    public BlockTest() {
        System.out.println("####构造方法体####");
    }
    public static void main(String[] args) {
        BlockTest bt1 = new BlockTest();
        BlockTest bt2 = new BlockTest();
    }
}
####静态代码块####
####构造块####
####构造方法体####
####构造块####
####构造方法体####
  • 执行顺序:静态代码块 > 构造块 > 构造方法体

main方法的详解

  • 语法格式:public static void main(String[] args) {}

MainTest.java

/*
* 编程实现main方法的测试
* */
package cn.itcast.day01.demo10;

public class MainTest {
   public static void main(String[] args) {
       System.out.println("main方法参数数组中元素个数是:" + args.length);
       for (int i = 0; i < args.length; i++) {
           System.out.println("下标为" + i + "的形参变量数值为:" + args[i]);
       }
   }
}
  • 打开cmd

  • 执行javac MainTest.java

  • 执行java MainTest 关羽 张飞 赵云 黄忠 马超

  • 执行结果:

main方法参数数组中元素个数是:5
下标为0的形参变量数值为:关羽
下标为1的形参变量数值为:张飞
下标为2的形参变量数值为:赵云
下标为3的形参变量数值为:黄忠
下标为4的形参变量数值为:马超

实例

我们之所以能够创建多个不同的对象,是因为我们可以无限制地访问构造方法。若希望限制创建对象的次数,我们就需要将构造方法私有化。

Singleton.java

package cn.itcast.day01.demo11;

public class Singleton {
    //2、声明本类型的引用指向本类类型的对象,使用private static关键字共同修饰
    private static Singleton sgtn = new Singleton();

    //1、私有化构造方法,使用private关键字修饰
    private Singleton() {
    }

    //3、提供公有的get方法负责将对象返回出去,使用public static关键字共同修饰
    public static Singleton getInstance() {
        return sgtn;
    }
}

SingletonTest.java

package cn.itcast.day01.demo11;

public class SingletonTest {
    public static void main(String[] args) {
        Singleton sgtn1 = Singleton.getInstance();
        Singleton sgtn2 = Singleton.getInstance();
        System.out.println(sgtn1 == sgtn2);
    }
}

单例设计模式

上一个例子中的实现方式就是饿汉式,下面再介绍一下懒汉式:

Singleton.java

package cn.itcast.day01.demo11;

public class Singleton {
    //2、声明本类型的引用指向本类类型的对象,使用private static关键字共同修饰
    private static Singleton sgtn = null;

    //1、私有化构造方法,使用private关键字修饰
    private Singleton() {}

    //3、提供公有的get方法负责将对象返回出去,使用public static关键字共同修饰
    public static Singleton getInstance() {
        if(null == sgtn) {
            sgtn = new Singleton();
        }
        return sgtn;
    }
}

饿汉式:加载类的同时就创建了对象。

懒汉式:当执行getInstance()方法时,才创建对象。

继承的由来和概念

Person.java

/*
编程实现Peson类的封装
*/
public class Person {
    private String name;
    private int age;
    
    public void setName(String name) {
        this.name = name;
    }
    
    public String getName() {
        return this.name;
    }
    
    public void setAge(int age) {
        if(age > 0 && age < 150) {
            this.age = age;
        }else {
            System.out.println("设置的年龄不合理!");
        }
    }
    
    public int getAge() {
        return this.age;
    }
    
    public void show() {
        System.out.println("我是" + getName() + ",今年" + getAge() + "岁了。");
    }
    
    public void eat(String food) {
        System.out.println(food + "真好吃!");
    }
    
    public void play(String toy) {
        System.out.println(toy + "真好玩!");
    }
}

Worker.java

/*
 编程实现worker类的封装
*/

public class Worker extends Person {
	
}

WorkerTest.java

/*
 编程实现Worker类的测试
*/
public class WorkerTest {
	public static void main(String[] args) {
		Worker w1 = new Worker();
		w1.show();
	}
}

执行结果:

我是null,今年0岁了。

将Worker类完善一下:

Worker.java

/*
 编程实现worker类的封装
*/

public class Worker extends Person {
	private int salary;
	
	public Worker() {}
	
	public Worker(String name, int age, int salary) {
		setName(name);
		setAge(age);
		setSalary(salary);
	}
	
	public void setSalary(int salary) {
		if(salary < 2200) {
			System.out.println("薪水不合理,低于最低标准!");
		}else {
			this.salary = salary;
		}
	}
	
	public int getSalary() {
		return salary;
	}
	
	public void work() {
		System.out.println("今天的代码真香!");
	}
}

WorkTest.java

/*
 编程实现Worker类的测试
*/
public class WorkerTest {
	public static void main(String[] args) {
		Worker w1 = new Worker();
		w1.show();
		
		System.out.println("--------------------");
		
		Worker w2 = new Worker("zhangfei", 30, 3000);
		w2.show();
		w2.eat("豆芽");
		w2.play("王者荣耀");
		w2.work();
	}
}

执行结果:

我是null,今年0岁了。
--------------------
我是zhangfei,今年30岁了。
豆芽真好吃!
王者荣耀真好玩!
今天的代码真香!

继承的特点

Person.java

/*
编程实现Peson类的封装
*/
public class Person {
    private String name;
    private int age;
    
	public Person() {
		System.out.println("Person()");
	}
	
	public Person(String name, int age) {
		System.out.println("Person(name, age)");
		setName(name);
		setAge(age);
	}
	
    public void setName(String name) {
        this.name = name;
    }
    
    public String getName() {
        return this.name;
    }
    
    public void setAge(int age) {
        if(age > 0 && age < 150) {
            this.age = age;
        }else {
            System.out.println("设置的年龄不合理!");
        }
    }
    
    public int getAge() {
        return this.age;
    }
    
    public void show() {
        System.out.println("我是" + getName() + ",今年" + getAge() + "岁了。");
    }
    
    public void eat(String food) {
        System.out.println(food + "真好吃!");
    }
    
    public void play(String toy) {
        System.out.println(toy + "真好玩!");
    }
}

打开cmd窗口;

执行javac WorkerTest.java

执行java WorkerTest

执行结果是:

Person()
我是null,今年0岁了。
--------------------
Person()
我是zhangfei,今年30岁了。
豆芽真好吃!
王者荣耀真好玩!
今天的代码真香!

可以看到,无论访问Worker类的有参构造方法还是无参构造方法,都执行了Person的无参构造方法。

Worker.java

/*
 编程实现worker类的封装
*/

public class Worker extends Person {
	private int salary;
	
	public Worker() {
		super(); //表示调用父类的无参构造方法,若没有加则编译器自动添加
		System.out.println("Worker()");
	}
	
	public Worker(String name, int age, int salary) {
		super();//表示调用父类的无参构造方法
		System.out.println("Worker(name, age, salary)");
		setName(name);
		setAge(age);
		setSalary(salary);
	}
	
	public void setSalary(int salary) {
		if(salary < 2200) {
			System.out.println("薪水不合理,低于最低标准!");
		}else {
			this.salary = salary;
		}
	}
	
	public int getSalary() {
		return salary;
	}
	
	public void work() {
		System.out.println("今天的代码真香!");
	}
}

再次编译并执行WorkerTest.java,执行结果与上面的没有区别,这是因为子类的构造方法会自动调用super()

Person()
我是null,今年0岁了。
--------------------
Person()
我是zhangfei,今年30岁了。
豆芽真好吃!
王者荣耀真好玩!
今天的代码真香!

这样当然是不符合我们的要求的,我们希望在Worker类中调用Worker的无参构造方法时调用Person的无参构造方法,调用Worker的有参构造方法时调用Person的有参构造方法,于是Worker.java代码可以改写:

/*
 编程实现worker类的封装
*/

public class Worker extends Person {
	private int salary;
	
	public Worker() {
		super(); //调用父类的无参构造方法
		System.out.println("Worker()");
	}
	
	public Worker(String name, int age, int salary) {
		super(name, age);//调用父类的有参构造方法
		System.out.println("Worker(name, age, salary)");
		setSalary(salary);
	}
	
	public void setSalary(int salary) {
		if(salary < 2200) {
			System.out.println("薪水不合理,低于最低标准!");
		}else {
			this.salary = salary;
		}
	}
	
	public int getSalary() {
		return salary;
	}
	
	public void work() {
		System.out.println("今天的代码真香!");
	}
}

方法重写的概念和使用

Worker.java

/*
 编程实现worker类的封装
*/

public class Worker extends Person {
	private int salary;
	
	public Worker() {
		super(); //表示调用父类的无参构造方法,若没有加则编译器自动添加
		System.out.println("Worker()");
	}
	
	public Worker(String name, int age, int salary) {
		super(name, age);//表示调用父类的无参构造方法
		System.out.println("Worker(name, age, salary)");
		setSalary(salary);
	}
	
	public void setSalary(int salary) {
		if(salary < 2200) {
			System.out.println("薪水不合理,低于最低标准!");
		}else {
			this.salary = salary;
		}
	}
	
	public int getSalary() {
		return salary;
	}
	
	public void work() {
		System.out.println("今天的代码真香!");
	}
	
	//自定义show()方法覆盖父类中继承的版本
	@Override //这是标注(注解),用于说明下面的方法是对父类方法的重写,若没有构成重写则编译报错
	public void show() {
		super.show();
        System.out.println("我的薪水是" + getSalary());
    }
}

WorkerTest.java

/*
 编程实现Worker类的测试
*/
public class WorkerTest {
	public static void main(String[] args) {
		Worker w1 = new Worker();
		//当子类重写show方法后,则下面调用的是重写以后的版本
		w1.show();
		
		System.out.println("--------------------");
		
		Worker w2 = new Worker("zhangfei", 30, 3000);
		w2.show();
		w2.eat("豆芽");
		w2.play("王者荣耀");
		w2.work();
	}
}

重新编译并执行``WorkTest.java`,执行结果是:

Person()
Worker()
我是null,今年0岁了。
我的薪水是0
--------------------
Person(name, age)
Worker(name, age, salary)
我是zhangfei,今年30岁了。
我的薪水是3000
豆芽真好吃!
王者荣耀真好玩!
今天的代码真香!

方法重写的原则

IDEA的下载方式

idea下载地址:https://www.jetbrains.com/idea/download/#section=windows

Dog类和DogTest类的实现

Animal.java:

package cn.itcast.day01.demo12;

public class Animal {
    private String name;
    private String color;

    public Animal() {
    }

    public Animal(String name, String color) {
        setName(name);
        setColor(color);
    }

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

    public void setColor(String color) {
        this.color = color;
    }

    public String getName() {
        return name;
    }

    public String getColor() {
        return color;
    }

    public void show() {
        System.out.println("名字:" + getName() + ",颜色:" + getColor());
    }
}

Dog.java:

package cn.itcast.day01.demo12;

public class Dog extends Animal {
    private int tooth;

    public Dog() {
    }

    public Dog(String name, String color, int tooth) {
        super(name, color);
        setTooth(tooth);
    }

    public int getTooth() {
        return tooth;
    }

    public void setTooth(int tooth) {
        if (tooth > 0) {
            this.tooth = tooth;
        }else {
            System.out.println("牙齿的数量不合理!");
        }
    }

    @Override
    public void show() {
        super.show();
        System.out.println("牙齿的数量是:" + getTooth());
    }
}

DogTest.java:

package cn.itcast.day01.demo12;

public class DogTest {
    public static void main(String[] args) {
        Dog d1 = new Dog();
        d1.show();

        Dog d2 = new Dog("铁憨憨", "白色", 30);
        d2.show();
    }
}

执行结果:

名字:null,颜色:null
牙齿的数量是:0
名字:铁憨憨,颜色:白色
牙齿的数量是:30

构造块和静态代码块

当我们new一个对象时,代码执行顺序是:静态代码块 --> 构造块 --> 构造方法,如下所示:

SuperTest.java:

package cn.itcast.day01.demo12;

public class SuperTest {
    {
        System.out.println("SuperTest类中的构造块");
    }

    static {
        System.out.println("SuperTest类中的静态代码块");
    }

    public SuperTest() {
        System.out.println("SuperTest类中的构造方法体");
    }

    public static void main(String[] args) {
        SuperTest st = new SuperTest();
    }
}
//执行结果:
SuperTest类中的静态代码块
SuperTest类中的构造块
SuperTest类中的构造方法体

但是,若此时有一个子类SubSuperTest继承了SuperTest类,并且同样有静态代码块、构造块和构造方法体,则执行顺序是:

SubSuperTest.java:

package cn.itcast.day01.demo12;

public class SubSuperTest extends SuperTest{
    {
        System.out.println("SuperTest类中的构造块");
    }

    static {
        System.out.println("SuperTest类中的静态代码块");
    }

    public SubSuperTest() {
        System.out.println("SuperTest类中的构造方法体");
    }

    public static void main(String[] args) {
        SubSuperTest st = new SubSuperTest();
    }
}
//执行结果:
SuperTest类中的静态代码块
SubSuperTest类中的静态代码块
SuperTest类中的构造块
SuperTest类中的构造方法体
SubSuperTest类中的构造块
SubSuperTest类中的构造方法体

由于创建SubSuperTest类时,会首先加载类,因此先加载父类SuperTest的静态构造块再加载子类SubSuperTest的静态构造块,类层级加载完毕以后,便应该加载对象层级了,所以先加载父类SuperTest的构造块和构造方法体,再加载子类SubSuperTest的构造块和构造方法体。

权限修饰符和包的定义

final修饰类和方法的作用

//idea中快捷键
ctrl+shift+/ 进行选中内容的多行注释
ctrl+/       进行当前行的单行注释

posted @ 2020-09-29 23:39  咕噜噜~  阅读(197)  评论(0编辑  收藏  举报