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

关于java对象的思考,布布扣,bubuko.com

时间: 2024-12-31 14:46:06

关于java对象的思考的相关文章

Java对象的创建

学了很久的java,是时候来一波深入思考了.比如:对象是如何在JVM中创建,并且被使用的.本文主要讲解下new对象的创建过程.要想更深入的了解建议去认认真真的看几遍<深入理解Java虚拟机>周志明写的. 首先自己想想:Person p = new Person() 这句话是干嘛的?废话,肯定是创建一个新对象的,那么JVM是怎么帮你创建的呢?在哪创建的?怎么在堆上分配内存的?你又是如何去根据变量找到对应的对象的?带着这些问题,继续往下看: 一.找到能生成对象的Class类 对象又不是孙猴子,石头

JVM —— Java 对象占用空间大小计算

零. 为什么要知道 Java 对象占用空间大小 缓存的实现: 在设计 JVM 内缓存时(不是借助 Memcached. Redis 等), 需要知道缓存的对象是否会超过 JVM 最大堆限制, 如果会超过要设置相应算法如 LRU 来丢弃一部分缓存数据以满足后续内容的缓存 JVM 参数设置: 如果知道对象会被创建, 可以帮助判断 -Xmx 需要设置多少 只是为了好玩 一. 对象的内存布局 HotSpot 虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头(Header).实例数据(Instan

利用Apache的commons-beanutils和commons-collections包实现Java对象的按属性排序

在日常工作中经常用到需要对java对象集合或者Map集合中的某个属性做排序,这个需求可以利用Apache的commons-beanutils和commons-collections包来实现,主要实现方式如下: public static <T> void sort(List<T> list, String property, boolean asc) { Comparator<?> comparator = ComparableComparator.getInstanc

Java对象的内存布局

Java对象的内存布局:对象头(Header),实例数据(Instance Data),对齐填充(Padding):另外:不同的环境结果可能有差异,我所在的环境是HotSpot虚拟机,64位Windows. 对象头 对象头在32位系统上占用8bytes,64位系统上占用16bytes. System.out.println("sizeOf(new Object()) = " + sizeOf(new Object())); sizeOf(new Object()) = 16 实例数据

JAVA对象头

#为了防止自己忘记,先记着,之前我一直以为<深入理解JAVA虚拟机>写错了来着. 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header),实例数据(Instance Data)和对齐填充(Padding). 也就是说  JAVA对象 = 对象头 + 实例数据 + 对象填充 对象头由两部分组成,一部分用于存储自身的运行时数据,称之为 Mark Word,另外一部分是类型指针,及对象指向它的类元数据的指针. 对象头 = Mark Word + 类型指针 (未开启指

Java对象及其引用 (1)

Java对象及其引用 [文章转载自:http://zwmf.iteye.com/blog/1738574] 说明:所有转载为个人学习存档使用,凡转载内容均注明转载出处.以后不再说明. 关于对象与引用之间的一些基本概念. 初学Java时,在很长一段时间里,总觉得基本概念很模糊.后来才知道,在许多Java书中,把对象和对象的引用混为一谈.可是,如果我分不清对象与对象引用, 那实在没法很好地理解下面的面向对象技术.把自己的一点认识写下来,或许能让初学Java的朋友们少走一点弯路. 为便于说明,我们先定

java对象分配

1.为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到哪些对象没用,这样就会对堆的所有区域进行扫描.而我们的很多对象都是朝生夕死的,如果分代的话,我们把新创建的对象放到某一地方,当GC的时候先把这块存“朝生夕死”对象的区域进行回收,这样就会腾出很大的空间出来. 2.年轻代中的GC     HotSpot JVM把年轻代分为了三部分:1个Eden

JAVA对象JSON数据互相转换的四种常见情况

1. 把java 对象列表转换为json对象数组,并转为字符串 JSONArray array = JSONArray.fromObject(userlist);    String jsonstr = array.toString(); 2.把java对象转换成json对象,并转化为字符串 JSONObject object = JSONObject.fromObject(invite);   String str=object.toString()); 3.把JSON字符串转换为JAVA 对

JAVA对象和XML文档、原来他们之间还有这一出

最近项目开发中遇到一个问题,访问接口不再通过url地址请求的方式,而是 通过socket发送xml格式的报文到指定服务器来进行信息的统一认证.. 因此组装xml格式的报文字符串以及解析服务器返回的xml格式的字符获得所需数据成了 解决问题的关键..在这之前,以为会有点难...做完之后,然并卵,也就那么一回事... LZ主要用的xStream类..这个类的完美地解决了XML文档和JAVA对象之间的转换.. 由于刚刚接触这个类...对于里面提供的很多功能还没细细挖掘..只是简单地实现了 我想要实现的