首页 > 代码库 > 关于java对象的思考

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