不可变对象和类
由不可变类创建的对象就是不可变对象,要使一个类成为不可变的,它必须满足下面的需求:
- 所有数据域都是私有的
- 没有修改器方法
- 没有一个访问器的方法,它会返回一个指向可变数据域的引用
看下面的代码:
public class Main { public static void main(String args[]) { Student student = new Student(11222333, "John"); java.util.Date dateCreatedDate = student.getDateCreated(); dateCreatedDate.setTime(200000); } } class Student { private int id; private String name; private java.util.Date dateCreated; public Student(int ssn, String newName){ //构造函数 id = ssn; name = newName; dateCreated = new java.util.Date(); } public int getId() { return id; } public String getName() { return name; } public java.util.Date getDateCreated() { return dateCreated; } }
变量的作用域
一个类的实例变量和静态变量称为类变量或数据域。在方法内部定义的变量称为局部变量。类的变量和方法可以在类中以任意顺序出现
public class Main { public static void main(String args[]) { Foo f = new Foo(); f.p(); } } class Foo { private int x = 0; private int y = 0; public Foo() { } public void p() { int x = 1; System.out.println("x = " + x); System.out.println("y = " + y); } }
运行结果:
x = 1
y = 0
this引用
关键字this是指向调用对象本身的引用名,一种常见的用法就是引用类的隐藏数据域。
class Foo { int i = 0; static double k = 0; void setTime(int i) { this.i = i; } static void setK(double k) { Foo.k = k; } }
另一种常见方法是让构造方法调用同一个类的另一个构造方法:
class Circle { private double radius; public Circle(double radius) { this.radius = radius; } public Circle() { this(1.0); } public double getArea() { return this.radius * this.radius * Math.PI; } }
类的抽象和封装
类抽象是将类的实现和使用分离,从类外可以访问的全部方法和数据域,以及期望这些成员如何行动的描述合称为类的合约
实例:
public class Main { public static void main(String args[]) { Scanner input = new Scanner(System.in); System.out.print("Enter yearly interest rate, for example, 8.25: "); double annualInterestRate = input.nextDouble(); System.out.print("Enter number of years as an integer: "); int numberOfYear = input.nextInt(); System.out.print("Enter loan amount, for example, 1200000.95: "); double loanAmount = input.nextDouble(); Loan loan = new Loan(annualInterestRate, numberOfYear, loanAmount); System.out.printf("The loan was created on %s\n" + "The monthly payment is %.2f\nThe total payment is %.2f\n", loan.getLoanDate().toString(), loan.getMonthlyPayment(), loan.getTotalPayment()); } } class Loan { private double annualInterestRate; private int numberOfYears; private double loanAmount; private java.util.Date loanDate; public Loan() { this(2.5, 1, 10000); } public Loan(double annualInterestRate, int numberOfYears, double loanAmount) { this.annualInterestRate = annualInterestRate; this.numberOfYears = numberOfYears; this.loanAmount = loanAmount; loanDate = new java.util.Date(); } public double getAnnualInterestRate() { return annualInterestRate; } public void setAnnualInterestRate(double annualInterestRate) { this.annualInterestRate = annualInterestRate; } public int getNumberOfYear() { return numberOfYears; } public void setNumberOfYear(int numberOfYears) { this.numberOfYears = numberOfYears; } public double getLoanAmount() { return loanAmount; } public void setLoanAmount(double loanAmount) { this.loanAmount = loanAmount; } public double getMonthlyPayment() { double monthlyInterestRate = annualInterestRate / 1200; double monthlyPayment = loanAmount * monthlyInterestRate / (1 - (Math.pow((1 / (1 +monthlyInterestRate)), numberOfYears * 12))); return monthlyPayment; } public double getTotalPayment() { double totalPayment = getMonthlyPayment() * numberOfYears * 12; return totalPayment; } public java.util.Date getLoanDate() { return loanDate; } }
类的设计原则
1、内聚性
类应该描述一个单一的实体,而所有的类操作应该在逻辑上互相配合,支持一个连贯性的目标
如果一个实体担负太多的职责,就应该按各自的职责分成几个类。例如:String类、StringBuffer类、StringBuilder类
2、一致性
遵循标准java程序设计风格和命名习惯。给类、数据域和方法选择有信息量的名字,选择名字要保持一致。
应该为类提供一个为构造默认实例的公共无参构造函数,如果不想让用户创建类的对象,可以在类中声明一个私有的构造方法。例如:Math类
3、封装性
使用private修饰符隐藏其数据,以免用户直接访问它,更易于维护。
如果想让数据域可读,只需提供get方法。如果想让数据域可更新,应该提供set方法
4、完整性
为了能在一个广泛的应用中使用,一个类应该通过属性和方法提供多种方案以适应用户的不同需求
例如:String提供了40多种很实用的方法