java-类和对象
目录
警告
本文最后更新于 2022-11-18,文中内容可能已过时,请谨慎使用。
注意
本文档属于个人笔记,个人水平有限,请酌情采纳,有任何错误可在评论区指出
类之间的常见关系
- 依赖(Dependency)
- (“use a”)
- 依赖关系使用虚线加箭头表示
- 如果一个类 A 的方法操纵了类 B 的对象,我们就说类 A 依赖于类 B
解释:学生编写程序需要使用电脑,因此学生对电脑产生了依赖
2.关联(Association)
- (“has a”)
- 关联关系使用实线加箭头表示
- 聚合关系意味着类 A 的成员变量中包含类 B
解释:一个老师可以有多名学生
3.继承(inheritance)
- (“is a”)
- 继承关系使用实线加三角形表示
4.聚合(Aggregation)
- 聚合关系使用实线加空心菱形表示
- 聚合是一种特殊的关联关系,它是较强的一种关联关系
- 强调集体和个体的关系
解释:一个班级有多个学生,类 Student
将成为类 Classes
的成员变量
5.组合(Composition)
- 组合是一种特殊的关联关系,它是较强的一种关联关系
- 强调整体和局部的关系
LocalDate 类
import java.time.LocalDate;
public class Main {
public static void main(String[]args) {
LocalDate localDate = LocalDate.now();
// plusDays会产生一个新对象,原对象不变, 100天后是哪一天
System.out.println(localDate.plusDays(100));
int year = localDate.getYear();
int month = localDate.getMonthValue();
int day = localDate.getDayOfMonth();
// 当前日期
System.out.println(year + "/" + month + "/" + day);
// 设置为本月1号
LocalDate start = localDate.minusDays(day - 1);
// 1号是星期几
System.out.println(start.getDayOfWeek().getValue());
}
}
构造方法的变量
不要在构造方法和其他方法中定义和成员变量同名的变量
public class Main {
public static void main(String[] args) {
Test t = new Test(1,"111");
// Error
System.out.println(t.id);
// Error
System.out.println(t.name);
}
}
class Test {
private int id;
private String name;
public Test(int a,String b) {
// 在构造方法中定义和成员变量相同的局部变量会使成员变量失效
// Error
int id = 11;
String name = "ok";
this.id = 10;
this.name = "okk";
}
}
访问器和更改器
- 只访问对象而不修改对象的方法有时称为访问器方法(accessor method)
- 访问对象并且修改对象的方法称为更改器方法(mutator method)
静态变量、静态方法、静态常量
静态方法:只需要访问静态变量时使用
public class Main {
public static void main(String[] args) {
Test t = new Test();
Test t1 = new Test();
Test t2 = new Test();
Test t3 = new Test();
System.out.println(t.getId());
System.out.println(t1.getId());
System.out.println(t2.getId());
t3.setId(10);
System.out.println(t3.getId());
System.out.println(Test.getNextId());
System.out.println(Test.NUMBER);
}
}
class Test {
public static final int NUMBER = 10;
private static int nextId = 1;
private int id;
public Test(){
id = nextId;
nextId++;
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
public static int getNextId() {
return nextId;
}
}
按值引用
Java
程序设计语言总是采用按值调用
public class StaticTest {
public static void main(String[] args)
{
/*
* Test 1: Methods can't modify numeric parameters
*/
System.out.println("Testing tripleValue:");
double percent = 10;
System.out.println("Before: percent=" + percent);
tripleValue(percent);
System.out.println("After: percent=" + percent);
/*
* Test 2: Methods can change the state of object parameters
*/
System.out.println("\nTesting tripleSalary:");
Employee harry = new Employee("Harry", 50000);
System.out.println("Before: salary=" + harry.getSalary());
tripleSalary(harry);
System.out.println("After: salary=" + harry.getSalary());
/*
* Test 3: Methods can't attach new objects to object parameters
*/
System.out.println("\nTesting swap:");
Employee a = new Employee("Alice", 70000);
Employee b = new Employee("Bob", 60000);
System.out.println("Before: a=" + a.getName());
System.out.println("Before: b=" + b.getName());
swap(a, b);
System.out.println("After: a=" + a.getName());
System.out.println("After: b=" + b.getName());
}
public static void tripleValue(double x) // doesn't work
{
x = 3 * x;
System.out.println("End of method: x=" + x);
}
public static void tripleSalary(Employee x) // works
{
x.raiseSalary(200);
System.out.println("End of method: salary=" + x.getSalary());
}
public static void swap(Employee x, Employee y)
{
Employee temp = x;
x = y;
y = temp;
System.out.println("End of method: x=" + x.getName());
System.out.println("End of method: y=" + y.getName());
}
}
class Employee // simplified Employee class
{
private String name;
private double salary;
public Employee(String n, double s)
{
name = n;
salary = s;
}
public String getName()
{
return name;
}
public double getSalary()
{
return salary;
}
public void raiseSalary(double byPercent)
{
double raise = salary * byPercent / 100;
salary += raise;
}
}
重载(overload)
方法签名:包括方法名和参数类型
注意返回类型不是方法签名的一部分,所以方法签名相同但是返回值不同不构成重载!
indexof(int)
indexof(int,int)
indexof(int,int,int)
indexof(String)
indexof(String,int)
如果多个方法有相同的名字、不同的参数,便产生了重载。
重写(override)
重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。
重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
重载和重写的区别
区别点 | 重载方法 | 重写方法 |
---|---|---|
参数列表 | 必须修改 | 一定不能修改 |
返回类型 | 可以修改 | 一定不能修改 |
异常 | 可以修改 | 可以减少或删除,一定不能抛出新的或者更广的异常 |
访问 | 可以修改 | 一定不能做更严格的限制(可以降低限制) |
构造函数初始化
静态初始化代码块(只调用 1 次)->选择指定构造函数->成员变量默认赋值->对象初始化代码块->构造函数执行完毕
public class Main {
public static void main(String[] args) {
// fill the staff array with three Employee objects
Employee[] staff = new Employee[3];
staff[0] = new Employee("Harry", 40000);
staff[1] = new Employee(60000);
staff[2] = new Employee();
// print out information about all Employee objects
for (Employee e : staff) {
System.out.println("name=" + e.getName() + ",id=" + e.getId() + ",salary="
+ e.getSalary());
}
}
}
class Employee {
// three overloaded constructors
public Employee(String n, double s) {
name = n;
salary = s;
}
public Employee(double s) {
// calls the Employee(String, double) constructor
this("Employee #" + nextId, s);
}
// the default constructor
public Employee() {
// name initialized to ""--see below
// salary not explicitly set--initialized to 0
// id initialized in initialization block
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
public int getId() {
return id;
}
private static int nextId;
private int id;
private String name = ""; // instance field initialization
private double salary;
// static initialization block
static {
Random generator = new Random();
// set nextId to a random number between 0 and 9999
nextId = generator.nextInt(10000);
}
// object initialization block
{
id = nextId;
nextId++;
}
}