关于java对象的思考

不可变对象和类

由不可变类创建的对象就是不可变对象,要使一个类成为不可变的,它必须满足下面的需求:

  • 所有数据域都是私有的
  • 没有修改器方法
  • 没有一个访问器的方法,它会返回一个指向可变数据域的引用

看下面的代码:

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多种很实用的方法

原文地址:https://www.cnblogs.com/bigjava/p/3833455.html