Skip to content

一、复习

1.1 方法的参数传递机制

1、基本数据类型:实参给形参传的是数据值的副本,形参接下来的修改与实参无关。

2、引用数据类型:实参给形参传的是地址值的副本,形参接下来对数组元素的修改与实参有关。当形参变量指向一个新的数组对象时,接下来的修改就与实参无关了。

1.2 方法调用的过程

  • 入栈:方法被调用时,就会在栈内存开辟一块空间,用于存储这个方法的局部变量、操作数栈等信息
  • 出栈:方法调用结束(要么方法体语句全部执行完,遇到 return 语句,遇到异常),就会释放这个方法占用的栈内存空间。
  • 栈内存的结构特点:先进后出(FILO,first in last out)或后进先出(LIFO,last in first out)

1.3 方法的重载(overload)

在同一个类中,方法名相同,形参列表不同(形参的类型、个数、顺序不同,与形参名无关)的两个或多个方法称为重载。重载与返回值类型、修饰符也无关。

image-20250705083903666

image-20250705084011277

1.4 可变参数

java
【修饰符】 class 类名{
    【修饰符】 返回值类型 方法名(【数据类型 普通参数名, 数据类型 普通参数名,】 数据类型... 可变参数名){
        //...
    }
}

一个方法最多只有 1 个可变参数,而是是最后一个参数。

可变参数部分在调用时,可以传入对应的数组 或 传入 0~n 个元素

1.5 递归

一个方法出现了自己调用自己的形式就是递归。递归调用必须有条件,或必须有出口,否则会出现 StackOverflowError 栈内存溢出错误。

1.6 类与对象

类:一类具有相同特征的事物的抽象描述。

对象:是这类事物中一个具体的个体、实体、实例。

java
【修饰符】 class 类名{
}
java
类名 对象名 = new 类名();

1.7 包

包的作用:管理不同的.java 文件,可以避免类的重名。

包名的命名习惯:

  • 全部小写
  • 单词之间使用.分割
  • 一般用公司域名倒置的形式:例如:com.atguigu.xxx

1.8 成员变量

java
【修饰符】 class 类名{
    【修饰符】 数据类型 成员变量名称;
}
静态变量实例变量
是否有 static有 static没有 static
是否被多个对象对象共享每一个对象独立的
是否依赖对象
在类的外部使用时类名.静态变量(推荐)
对象名.静态变量(不推荐)
对象名.实例变量

image-20250705085250393

二、类的成员

2.1 类的成员之一:成员变量(续)

成员变量:field 字段

2.1.1 成员变量是引用数据类型

案例演示

除了 8 种基本数据类型,以及 String 类型,其他的像数组、自己定义的类都可以当做数据类型。

java
package com.atguigu.field;

public class Husband {//丈夫
    public String name;
    public Wife wife;
}
java
package com.atguigu.field;

public class Wife {//妻子
    public String name;
    public Husband husband;
}
java
package com.atguigu.field;

public class TestHusbandWife {
    public static void main(String[] args) {
        //创建一个Husband类的对象
        Husband h = new Husband();
        h.name = "李刚";

        //创建一个Wife类的对象
        Wife w = new Wife();
        w.name = "翠花";

        /*
        一个对象名后面能.出什么,要看它是什么类型的对象。
        h是Husband类型的,它就可以.出Husband的成员,即h.name和h.wife都OK。
        此时h.wife是Wife类型的,它就可以.出Wife类的成员,即可以 h.wife.name 或  h.wife.husband
         */
        //System.out.println("男:" + h.name +",他的妻子的名字:" + h.wife.name);
        //上面这句代码编译没问题,但是运行时会报错,h.wife是null,会发生空指针异常

//        h.wife = 一个Wife类型的对象;
        h.wife = w;
        System.out.println("男:" + h.name +",他的妻子的名字:" + h.wife.name);
        w.husband = h;
        System.out.println("女:" + w.name +",她的丈夫的名字:" + w.husband.name);
    }
}

练习题

java
package com.atguigu.exer5;

//(1)声明一个MyDate类型,有属性:年year(int类型),月month(int类型),日day(int类型)
public class MyDate {//日期
    public int year;//年
    public int month;//月
    public int day;//日
}
java
package com.atguigu.exer5;

public class TestMyDate {
    public static void main(String[] args) {
        //(2)在测试类TestMyDate类中,创建两个日期对象,一个日期赋值为今年六一儿童节日期,
        // 一个日期赋值为今年程序员节日期,并显示
        MyDate childrenDay = new MyDate();
        childrenDay.year = 2025;
        childrenDay.month = 6;
        childrenDay.day = 1;
        System.out.println("今年六一儿童节:" + childrenDay.year +"年" + childrenDay.month+"月" + childrenDay.day+"日");

        MyDate programDay = new MyDate();
        programDay.year =2025;
        programDay.month =10;
        programDay.day =24;
        System.out.println("今年程序员节:" + programDay.year +"年" + programDay.month+"月" + programDay.day+"日");
    }
}
java
package com.atguigu.exer5;

//(3)声明另一个Employee类型,有属性:姓名name(String类型),生日birthday(MyDate类型)
public class Employee {//员工
    public String name;
    public MyDate birthday;
    //只要是8种以外的数据类型,都是引用数据类型,
    // 默认值是null,null代表没有对象给它赋值
}
java
package com.atguigu.exer5;

public class TestEmployee {
    public static void main(String[] args) {
//        (4)在测试类TestEmployee中的main中,创建两个员工对象,并为他们的姓名和生日赋值,并显示员工的姓名和生日
        Employee e1 = new Employee();
        e1.name ="张三";

       e1.birthday = new MyDate();
        //这种写法,是把变量的声明与给变量的赋值操作分开了
        //声明在Employee类中 MyDate birthday;
        //这里只是赋值。至于赋值什么东西?要看它什么类型,是MyDate类,就给它一个MyDate类型的对象
        e1.birthday.year = 1996;
        e1.birthday.month = 5;
        e1.birthday.day = 1;

        System.out.println("e1的信息:" + e1.name +",生日:"  +e1.birthday.year +"年" + e1.birthday.month+"月" + e1.birthday.day+"日");

        Employee e2 = new Employee();
        e2.name ="李四";

        MyDate my = new MyDate();
        my.year = 2000;
        my.month = 6;
        my.day = 1;
        e2.birthday = my;

        System.out.println("e2的信息:" + e2.name +",生日:"  +e2.birthday.year +"年" + e2.birthday.month+"月" + e2.birthday.day+"日");

    }
}

2.1.2 成员变量内存分析

1、JVM 内存结构

JVM 架构图如下:

img

JVM 运行时数据区:

image-20250620174513628

JDK7 和 8 版本每一块内存区域说明:

内存区域JDK7JDK8
方法区- 实现为永久代
- 类信息(类元数据)
- 运行时常量池
- JIT 编译后的代码
- 静态变量
-实现为元空间,位于本地内存(Native Memory)
- 类信息(类元数据)
- 运行时常量池
- JIT 编译后的代码
- 对象实例(包括数组)
- 字符串常量池(JDK7 从永久代移至堆)
- 对象实例(包括数组)
- 字符串常量池
- 静态变量(JDK8 从永久代移至堆)
Java 虚拟机栈- 栈帧:局部变量表、操作数栈、动态链接、方法出口与 JDK7 相同
本地方法栈- Native 方法调用的栈帧与 JDK7 相同
程序计数器当前线程执行的字节码指令地址与 JDK7 相同

2、实例变量的内存分析

image-20250705095459999

3、静态变量与实例变量的内存分析

image-20250705095922141

4、引用数据类型成员变量的内存分析

image-20250705102322743

说明:凡是引用数据类型的成员变量,它们的默认值是 null,如果没有给它赋值对象,通过它们.xx 的时候就会发生空指针异常,因为它们没有指向任何内存,找不到对应的数据。

2.2 类的成员之二:构造器

构造器:constructor

2.2.1 构造器的作用

构造器的作用是为对象的实例变量初始化或赋值的,在new对象的同时给它们赋值。

2.2.2 构造器如何声明和使用

  • 每一个类都有构造器
  • 如果一个类,程序员没有给它写构造器,那么编译器就会给它自动添加一个默认的无参构造。
  • 程序员也可以手动编写构造器,你可以编写无参构造,也可以编写有参构造。但是要注意,一旦你手动编写了构造器(无论你写的是无参还是有参的),编译器就不会给你自动添加默认的无参构造。
  • 构造器与方法很像,但是不一样。
    • 构造器没有返回值类型,也不能写返回值类型
    • 构造器的修饰符只能是 public、protected、缺省(不写)、private 四选 1 ,不能加 static、final 等其他单词
    • 构造器的名字必须与类名完全一致,包括大小写

image-20250705102930572

image-20250705103438388

image-20250705103757703

声明语法格式:

java
【修饰符】 class 类名{
    【public或protected或缺省或private】 类名(){//无参构造

    }
    【public或protected或缺省或private】 类名(形参列表){//有参构造
        实例变量 = 形参名;
    }
}

2.2.3 构造器可以用快捷键生成

image-20250705104728290

image-20250705105121087

java
package com.atguigu.constructor;

public class Book {
    public String name;
    public double price;

    //快捷键 Alt + Insert,部分同学的键盘模式,需要同时按Fn
    public Book() {//无参构造
    }

    public Book(String name, double price) {//全参构造
        this.name = name;
        this.price = price;
    }

    public Book(String name) {//部分参数构造器
        this.name = name;
    }
    //按照上面的代码,程序员有就有3种方式来创建Book对象
}

2.4.4 this 关键字

this 代表当前对象,在构造器中表示你正在 new 的哪个对象。

用法:

  • ths.实例变量:当实例变量与形参等局部变量重名时,需要在实例变量前面加 this.以区分。
  • this()this(参数):调用本类的其他构造器。它们必须在构造器的首行。
  • this.方法() :等单独讲成员方法的时候再说,这种用法几乎可以忽略不计,因为这种情况,this.都是省略。

image-20250705111209767

2.4.5 示例代码

示例 1:有默认无参构造

java
package com.atguigu.constructor;

public class Student {
    public String name;
    public int score;
}
java
package com.atguigu.constructor;

public class TestStudent {
    public static void main(String[] args) {
        Student s = new Student(); //默认的无参构造
        System.out.println(s.name+"," + s.score);
    }
}

示例 2:没有默认无参构造

java
package com.atguigu.constructor;

public class Teacher {
    public String name;
    public double salary;

    public Teacher(String n, double s) {
        name = n;
        salary = s;
    }
}
java
package com.atguigu.constructor;

public class TestTeacher {
    public static void main(String[] args) {
//        Teacher t1 = new Teacher();//报错,没有默认的无参构造
        Teacher t2 = new Teacher("柴林燕", 15000);
    }
}

示例 3:手动定义无参和有参构造

java
package com.atguigu.constructor;

public class Employee {
    public String name;
    public int age;
    public char gender;

    public Employee(){//无参构造

    }
    public Employee(String n, int a, char g){//有参构造
        name = n;
        age = a;
        gender = g;
    }
}
java
package com.atguigu.constructor;

public class TestEmployee {
    public static void main(String[] args) {
        //用无参构造创建Employee对象
        Employee e1 = new Employee();
        System.out.println("e1姓名:" + e1.name +",年龄:" + e1.age +",性别:" + e1.gender);

        //用有参构造创建Employee对象
        Employee e2 = new Employee("李刚", 25, '男');
        System.out.println("e2姓名:" + e2.name +",年龄:" + e2.age +",性别:" + e2.gender);
    }
}

示例 4:构造器不能加返回值类型

java
package com.atguigu.constructor;

public class Circle {
    public double radius;

    public void Circle(){//不是构造器
        System.out.println("我是构造器????");
    }
}
java
package com.atguigu.constructor;

public class TestCircle {
    public static void main(String[] args) {
        Circle c = new Circle();//用的是默认的无参构造
        c.Circle();//调用普通方法
    }
}

示例 5:快捷键生成构造器

java
package com.atguigu.constructor;

public class Book {
    public String name;
    public double price;

    //快捷键 Alt + Insert,部分同学的键盘模式,需要同时按Fn
    public Book() {//无参构造
    }

    public Book(String name, double price) {//全参构造
        this.name = name;
        this.price = price;
    }

    public Book(String name) {//部分参数构造器
        this.name = name;
    }
    //按照上面的代码,程序员有就有3种方式来创建Book对象
}

示例 6:this 调用本类构造器

java
package com.atguigu.constructor;

public class Goods {
    public int id;
    public String name;
    public double price;
    public int stock;
    public String date;

    public Goods() {
        System.out.println("一个商品对象被创建了");
    }

    public Goods(int id, String name, double price) {
        this();//调用本类无参构造
        this.id = id;
        this.name = name;
        this.price = price;
    }

    public Goods(int id, String name, double price, int stock, String date) {
//        this.id = id;
//        this.name = name;
//        this.price = price;
        this(id,name,price);//调用本类另一个有参构造,为id,name,price属性赋值
        this.stock = stock;
        this.date = date;
    }
}

2.3 面向对象基本特征之一:封装

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

2.3.1 为什么有封装?

生活中快递包裹的意义:

  • 保护隐私
  • 为了安全
  • 便于运输

Java 中类的封装的意义:

  • 保护隐私:有时候会故意隐藏类的内部实现细节,不需要使用者了解过多。例如:String 代表一串字符,早期用的是 char[]存储一组字符,现在用 byte[]存储一组字符
  • 便于维护和使用:例如 String,内部的实现细节变化了,不影响外部的使用

封装的层面可大可小:

  • 大:达到项目的层面,例如:咱们的项目调用 AI 大模型项目,咱们项目调用支付宝的支付功能,无需了解也无从得知它们的内部实现细节。
  • 小:属性的私有化

2.3.2 权限修饰符

Java 给我们提供了 4 种权限修饰符的情况,共有 3 个单词:

private缺省(不写)protectedpublic
本类
本包×
跨包的子类××
跨包的非子类×××

1、类(不含内部类)也有权限修饰符:只有 2 种,public 或缺省。

  • public 的类,可以跨包使用
  • 缺省的非公共的类,不可以跨包使用。

2、类的成员也可以有权限修饰符:四种都可以

类的成员有:成员变量、构造器、成员方法、成员内部类、代码块。这里先以成员变量为例演示。

案例 1

java
package com.atguigu.encapsolation.one;

public class Student {//公共的
}
/*class Student {//缺省的
}*/
/*
protected class Student {//错误,不可以在class前面写private和protected
}*/
java
package com.atguigu.encapsolation.two;

import com.atguigu.encapsolation.one.Student;

public class TestStudent {
    public static void main(String[] args) {
        Student s = new Student();
    }
}

案例 2

java
package com.atguigu.encapsolation.one;

public class Father {//父亲
    private int a;
    int b;
    protected int c;
    public int d;

    public void show(){//成员方法,本类的方法,可以访问本类的所有成员变量(不讨论静态非静态问题),只看权限修饰符问题
        System.out.println("a = " + a);
        System.out.println("b = " + b);
        System.out.println("c = " + c);
        System.out.println("d = " + d);
    }
}
java
package com.atguigu.encapsolation.one;

public class SamePackageTest {
    public static void main(String[] args) {
        Father f = new Father();
//        System.out.println("f.a = " + f.a);//因为a是private,出了Father就不可以直接访问
        System.out.println("f.b = " + f.b);
        System.out.println("f.c = " + f.c);
        System.out.println("f.d = " + f.d);
    }
}

跨包:

java
package com.atguigu.encapsolation.two;


import com.atguigu.encapsolation.one.Father;

//Son类继承Father,即Son类是Father类的子类
public class Son extends Father {//儿子
    public void print(){
//        System.out.println("a = " + a);
//        System.out.println("b = " + b);
        System.out.println("c = " + c);
        System.out.println("d = " + d);
        //跨包的子类中,只能访问父类中public和protected的成员,不可以访问父类中private和缺省的
    }
}
java
package com.atguigu.encapsolation.two;

import com.atguigu.encapsolation.one.Father;

public class DifferentPackageTest {
    public static void main(String[] args) {
        Father f = new Father();
//        System.out.println("f.a = " + f.a);//错误
//        System.out.println("f.b = " + f.b);//错误
//        System.out.println("f.c = " + f.c);//错误
        System.out.println("f.d = " + f.d);
        //跨包非子类,只有public可见,其他都不可见
    }
}

2.3.3 属性私有化

属性私有化是指给类的成员变量加 private 修饰。

第一步:给成员变量加 private

第二步:给这些成员变量加 get/set 方法

  • get/set 方法的命名规则,不能随意,习惯上都是 get/set +属性名,且属性名的首字母改为大写
  • 其中 boolean 类型属性,get 方法一般把 get 单词换成 is
  • 当成员变量是静态的,那么它们的 get/set 也是静态的。
    • 在静态的 set 方法中,形参与静态变量重名时,通过“类名.静态变量”进行区分
  • 当成员变量是非静态的,它们的 get/set 也是非静态的
    • 在非静态的 set 方法中,形参与实例变量重名时,通过“this.实例变量”进行区分
java
package com.atguigu.encapsolation.one;

public class Rectangle {
   /* public double length;
    public double width;*/
    private double length;
    private double width;

    public Rectangle() {
    }

    public Rectangle(double length, double width) {
        if(length<=0 || width<=0){
            System.out.println("长、宽必须是正数");
            return;
        }
        this.length = length;
        this.width = width;
    }

    //set:设置或修改某个属性的值
    public void setLength(double length){
        if(length<=0){
            System.out.println("长必须是正数");
            return;
        }
        this.length = length;
    }
    public void setWidth(double width){
        if(width<=0){
            System.out.println("宽必须是正数");
            return;
        }
        this.width = width;
    }

    //get是用于获取某个属性的值
    public double getLength(){
        return length;
    }
    public double getWidth(){
        return width;
    }

}
java
package com.atguigu.encapsolation.one;

public class TestRectangle {
    public static void main(String[] args) {
       /* Rectangle r1 = new Rectangle();
        r1.length = 6;
        r1.width = 4;
        System.out.println("r1的长和宽:" + r1.length +"," +r1.width);

        Rectangle r2 = new Rectangle(9,5);
        System.out.println("r2的长和宽:" + r2.length +"," +r2.width);

        Rectangle r3 = new Rectangle();
        r3.length = -8;
        r3.width = -6;
        System.out.println("r3的长和宽:" + r3.length +"," +r3.width);

        Rectangle r4 = new Rectangle(-9,-3);
        System.out.println("r4的长和宽:" + r4.length +"," +r4.width);*/
        //上面的代码必须对应length和width是public的情况

        Rectangle r1 = new Rectangle();
        r1.setLength(6);
        r1.setWidth(4);
        System.out.println("r1的长和宽:" + r1.getLength() +"," +r1.getWidth());

        Rectangle r2 = new Rectangle(9,5);
        System.out.println("r2的长和宽:" + r2.getLength() +"," +r2.getWidth());
        r2.setWidth(6);
        System.out.println("r2的长和宽:" + r2.getLength() +"," +r2.getWidth());
    }
}

2.3.4 可以用快捷键生成 get/set

image-20250705143459322

image-20250705143548837

java
package com.atguigu.encapsolation.one;

public class Employee {
    //属性私有化
    private static String company;//公司名
    private String name;
    private double salary;
    private boolean marry;

    //快捷键Alt+ Insert,部分同学可能需要同时按Fn
    public static String getCompany() {
        return company;
    }

    public static void setCompany(String company) {
        Employee.company = company;
//        this.company = company;//错误
    }

    public boolean isMarry() {
        return marry;
    }

    public void setMarry(boolean marry) {
        this.marry = marry;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
java
package com.atguigu.encapsolation.one;

public class TestEmployee {
    public static void main(String[] args) {
        Employee e1 = new Employee();
        e1.setName("张三");
        e1.setSalary(15000);
        e1.setMarry(true);
        System.out.println("e1的姓名:" + e1.getName() +",薪资:" + e1.getSalary() +",婚否:" + e1.isMarry());

        Employee e2 = new Employee();
        e2.setName("李四");
        e2.setSalary(12000);
        e2.setMarry(false);
        System.out.println("e2的姓名:" + e2.getName() +",薪资:" + e2.getSalary() +",婚否:" + e2.isMarry());
    }
}

2.4 类的成员之三:成员方法

2.4.1 静态方法和非静态方法

方法:method,在别的语言中,习惯叫做 function 函数。

在 Java 中方法是不能独立存在的,必须写在类中,即方法是类的成员。

成员方法可以分为 2 类:

  • 静态方法,又称为类方法
  • 非静态方法,又称为实例方法
静态方法非静态方法/实例方法
方法的前面有没有 static有 static没有 static
方法里面是否可以直接访问本类的其他成员只能访问本类的静态成员可以访问本类的所有成员
是否可以出现 this不可以出现 this可以出现 this
是否依赖当前类的对象不依赖依赖
跨类调用时类名.静态方法(推荐)
对象名.静态方法(不推荐,IDEA 不主动提示)
对象名.非静态方法

该如何选择呢?什么时候用静态方法,什么时候用非静态方法呢?

如果在这个方法中,需要访问本类的 非静态成员(实例变量等),那么这个方法必须是非静态的方法。

如果在这个方法中,只访问本类的 静态成员,理论上这个方法可以是静态的,也可以是非静态的,但是建议是静态的。

java
package com.atguigu.method;

public class Chinese {//中国人
    //country是国家名,每一个中国人应该共享同一个国家名,所以必须是static
    private static String country;//国家名   静态变量或称为类变量

    //name和age是每一个人独立的,所以它们不能是static
    private String name;//姓名   实例变量
    private int age;//年龄   实例变量

    //构造器 快捷键 Alt + Insert
    public Chinese() {//无参构造
    }

    public Chinese(String name, int age) {//有参构造
        this.name = name;
        this.age = age;
    }

    //get/set方法  快捷键 Alt + Insert
    public static String getCountry() {
        return country;
    }

    public static void setCountry(String country) {
        Chinese.country = country;
    }

    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 static void show(){//静态方法,或类方法
        System.out.println("国家名:" + country);
//        System.out.println("姓名:" + name);//报错
//        System.out.println("年龄:" + age);//报错
    }

    public void display(){//非静态方法,或实例方法
        System.out.println("国家名:" + country);
        System.out.println("姓名:" + name);
        System.out.println("年龄:" + age);
    }
}

2.4.2 方法的内存分析

image-20250705163118262

所有方法都有调用者:

  • 静态方法:它的调用者时这个类本身
  • 非静态方法:它的调用者是某个对象,在当前非静态方法中,由 this 来代表调用这个方法的当前对象。同时 this 可以取得这个对象的所有的属性值。

2.4.3 案例

1、案例 1

java
package com.atguigu.exer5_2;

//(1)声明一个MyDate类型,有属性:年year(int类型),月month(int类型),日day(int类型)
public class MyDate {//日期
    private int year;//年
    private int month;//月
    private int day;//日

    //构造器,快捷键Alt  + Insert
    public MyDate() {
    }

    public MyDate(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
    //get/set

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public int getMonth() {
        return month;
    }

    public void setMonth(int month) {
        this.month = month;
    }

    public int getDay() {
        return day;
    }

    public void setDay(int day) {
        this.day = day;
    }

    public String getInfo(){
        return year +"年" + month +"月" + day + "日";
    }
}
java
package com.atguigu.exer5_2;

public class TestMyDate {
    public static void main(String[] args) {
        //(2)在测试类TestMyDate类中,创建两个日期对象,一个日期赋值为今年六一儿童节日期,
        // 一个日期赋值为今年程序员节日期,并显示
        MyDate childrenDay = new MyDate();
        childrenDay.setYear(2025);
        childrenDay.setMonth(6);
        childrenDay.setDay(1);
       // System.out.println("今年六一儿童节:" + childrenDay.getYear() +"年" + childrenDay.getMonth()+"月" + childrenDay.getDay()+"日");
        System.out.println("今年六一儿童节:" + childrenDay.getInfo());

        MyDate programDay = new MyDate();
        programDay.setYear(2025);
        programDay.setMonth(10);
        programDay.setDay(24);
//        System.out.println("今年程序员节:" + programDay.getYear() +"年" + programDay.getMonth()+"月" + programDay.getDay()+"日");
        System.out.println("今年程序员节:" + programDay.getInfo());
    }
}
java
package com.atguigu.exer5_2;

//(3)声明另一个Employee类型,有属性:姓名name(String类型),生日birthday(MyDate类型)
public class Employee {//员工
    private String name;
    private MyDate birthday;

    //构造器,快捷键Alt  + Insert
    public Employee() {
    }
    public Employee(String name, MyDate birthday) {
        this.name = name;
        this.birthday = birthday;
    }
    //手写,单独定制
    public Employee(String name, int year, int month, int day){
        this.name = name;
        birthday = new MyDate(year, month, day);//=右边用的是MyDate类的构造器,意味着MyDate类须有一个全参构造
    }

    //get/set,快捷键Alt  + Insert
    public String getName() {
        return name;
    }

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

    public MyDate getBirthday() {
        return birthday;
    }

    public void setBirthday(MyDate birthday) {
        this.birthday = birthday;
    }

    public String getInfo(){
        return "姓名:" + name +",生日:" + birthday.getInfo();
    }
}
java
package com.atguigu.exer5_2;

public class TestEmployee {
    public static void main(String[] args) {
//        (4)在测试类TestEmployee中的main中,创建两个员工对象,并为他们的姓名和生日赋值,并显示员工的姓名和生日
        Employee e1 = new Employee();
        e1.setName("张三");

       /* MyDate date = new MyDate(1996,12,1);
        e1.setBirthday(date);*/

        //下面这句代码涉及到一个名词:匿名对象
        e1.setBirthday(new MyDate(1996,12,1));

        System.out.println("e1的信息:" + e1.getInfo());

        Employee e2 = new Employee();
        e2.setName("李四");

        MyDate my = new MyDate();
        my.setYear(2000);
        my.setMonth(6);
        my.setDay(1);
        e2.setBirthday(my);

        System.out.println("e2的信息:" + e2.getInfo());

        Employee e3 =new Employee("王五",2001,2,3);
        System.out.println("e3的信息:" + e3.getInfo());

    }
}

2、案例 2

java
package com.atguigu.exer2_2;

public class Triangle {
    private double a;
    private double b;
    private double c;

    public Triangle() {
    }

    public Triangle(double a, double b, double c) {
        //(1)边长不能为负数或0
        //(2)三角形要求任意两边之和大于第三边
        if(a<=0 || b<=0 || c<=0 || a+b<=c || b+c<=a ||a+c<=b){
            System.out.println(a+"," + b +"," + c +"的值无法构成三角形");
        }else {
            this.a = a;
            this.b = b;
            this.c = c;
        }
    }

    //get/set
    public double getA() {
        return a;
    }

    public void setA(double a) {
        this.a = a;
    }

    public double getB() {
        return b;
    }

    public void setB(double b) {
        this.b = b;
    }

    public double getC() {
        return c;
    }

    public void setC(double c) {
        this.c = c;
    }

    //其他方法
    public double area(){
        double p = (a+b+c)/2;
        return Math.sqrt(p * (p-a) * (p-b) * (p-c));
    }

    public double perimeter(){
        return a+b+c;
    }

    public String getInfo(){
        return "三边长:" + a + "," + b +"," + c +
                ",面积:" + area() +
                ",周长:" + perimeter();
    }
}
java
package com.atguigu.exer2_2;

public class TestTriangle {
    public static void main(String[] args) {
        Triangle t1 = new Triangle();
        t1.setA(6);
        t1.setB(6);
        t1.setC(6);
        System.out.println(t1.getInfo());

        Triangle t2 = new Triangle(3,4,5);
        System.out.println(t2.getInfo());

        Triangle t3 = new Triangle(1,1,5);
        System.out.println(t3.getInfo());
    }
}

2.4.4 标准的 Javabean

bean:豆

java:爪哇岛,印尼产咖啡豆的地方

java 的类,通常被比喻为咖啡豆

标准的 Javabean 有一些约定成俗的潜规则:

  • 所有的属性都是 private
  • 为他们提供公共的 get/set 方法
  • 保留无参构造
  • 至于有参构造,可选
  • 建议重写 hashCode、equals、toString 等(下周再讲)
  • 这个类是具体的,而不是抽象的(关于抽象类也是下周讲)