对象与对象变量:

要想使用对象,就必须首先构造对象,并指定其初始状态,然后,对对象应用方法。

在Java中,使用构造器构造新实例。构造器是一种特殊的方法,用来构造并初始化对象。

在实际开发中,通常需要将对象存放在一个变量中来达到多次使用的目的。

在这里,birth指向了Date对象的存储的地方的引用。

Date birthday = new Date();

在对象与对象变量直接存在着一个重要的区别,例如:

Date deadline;  //deadline dosen't refer to any object;

定义了一个对象变量,它可以引用Date类型的对象,但是,一定要认识到:变量deadline不是一个对象,实际上也没有引用一个对象。并且不能用任何Date方法应用与这个变量上

s = deadline.toString(); // not yet

在这里,将会产生编译错误。

首先,必须初始化变量deadline,可以用新构造的对象初始化,也可以引用一个已存在的变量。

deadline = new Date() //新构造对象
//
//或者
Date birthday = new Date();
deadline = birthday; //引用一个已存在对象  

当引用一个已存在的变量时,两个变量引用同一个对象:

在Java开发中,一定要认识到,一个对象变量并没i月实际包含一个对象,而仅仅使用一个对象,任何对象变量的值都是对存储在另外一个地方的一个对象的引用。

 

 

 

构造器:

首先来看一个Employee类:

class Employee
{
// instance fields
private String name;
private double salary;
private LocalDate hireDay;
// constructor 构造器
public Employee(String n, double s, int year, int month, int day)
{
name = n;
salary = s;
hireDay = LocalDate.of(year, month, day);
}
// a method
public String getName()
{
return name;
}
// more methods
. . .
}

该类的构造器与类同名,在构造Employee类的对象时,构造器会运行,并将实例初始化为所希望的状态。

例如,当使用下面代码实例化时:

new Employee("James Bond", 100000, 1950, 1, 1);

将会把实例域设置为:

name = "James Bond";
salary = 100000;
hireDay = LocalDate.of(1950, 1, 1); // January 1, 1950

构造器与其他方法有一个区别,即构造器伴随着new操作符被调用并且没有返回类型,而不能通过一个对象调用构造器,如下将会产生编译错误。

james.Employee("James Bond", 250000, 1950, 1, 1) // ERROR

重载:

一个类可以拥有多个构造器。

如果在一个类中,拥有多个方法,每个方法具有相同的名字,不同的参数,便产生了重载。编译器必须挑选出具体执行那个方法。

通常,多个具有相同名字不同参数的方法,是通过它们的签名来辨识的。

什么是方法的签名?

一个方法的签名即为它的方法名称,以及参数类型。注意,返回类型并不属于一个方法的签名!也就是说,不能具有相同名字,相同参数,而返回类型不同的两个方法。

 

默认域初始化:

如果在构造器中没有显式的给域赋予初始值,那么域会被自动地赋予默认值,数值为0,布尔值为false,对象引用为null。

这是域与局部变量的主要不同点。局部变量必须明确地初始化。

 

无参数的构造器:

很多类都包含一个无参数的构造函数,对象由构造函数创建时,状态会被设置为适当的默认值,如下为Employee类的无参数构造函数:

public Employee()
{
name = "";
salary = 0;
hireDay =new Date();
}

如果一个类没有编写构造器的话,那么系统就会提供一个无参数构造器。

 

调用另一个构造器:

如果构造器的第一个语句形如this(...),这个构造器将会调用同一个类的另一个构造器,下面是一个典型的例子:

public Employee(double s){
this("Employee ",s);
}

当调用new Employee(60)时,Employee(double)构造器将调用Employee(String,double)构造器。

 

初始化块:

 通常,初始化数据域有三种方法,一种是在构造器设置,一种是在声明中赋值,还有一种是初始化话块,只要构造类的对象,这些块就会被执行。

class Employee
{
private static int nextId;
private int id;
private String name;
private double salary;
// object initialization block 初始化块
{
id = nextId;
nextId++;
}
public Employee(String n, double s)
{
name = n;
salary = s;
}
public Employee()
{
name = "";
salary = 0;
}
. . .
}

 由于初始化数据域有多种途径,所以可能会有些混乱,下面是调用构造器的具体处理步骤:

1.所有数据域被初始化默认值。

2.按照类声明中出现的次序,依次执行所有域初始化语句和初始化块。

3.如果构造器第一行调用了第二个构造器,则执行第二个构造器的主体。

4.执行这个构造器的主体。

 

不要编写返回引用可变对象的访问器方法:

例如:

class Employee
{
private Date hireDay;
. . .
public Date getHireDay()
{
return hireDay; // Bad
}
. . .
}

 

这样会破坏封装性,即可以不通过Hireday的设置器方法就能改变Hireday,具体如下代码:

Employee harry = . . .;
Date d = harry.getHireDay();
double tenYearsInMilliSeconds = 10 * 365.25 * 24 * 60 * 60 * 1000;
d.setTime(d.getTime() - (long) tenYearsInMilliSeconds);
// let's give Harry ten years of added seniority

出错的原因即为d和harry.hireDay引用同一个对象,参见图:

实际上,返回对象应对其进行克隆,并返回该克隆对象。

 

 

 

 

final实例域:

可以将实例域定义为final,构建对象时必须初始化这样的域,也就是说,确保在每一个构造器执行之后,这个域的值被设置,并且在后面的从早中,不能够在对它进行修改。

通常,不推荐是哦那个final修饰符应用于可变的类,如下:

private final Date hiredate;

这仅仅意味着,存储在hiredate变量的对象引用不可变,也就是说永远指向同一个对象引用,但任何方法都可以对hiredate引用的对象调用setTime更改器来改变该对象。

 

静态域与静态方法:

如果将域定义为static,每个类中只有一个这样的域。而每一个对象对于所有的实例域却都有一份自己的拷贝。静态域是所有对象共享的,如这里给Employee类添加一个实例域id和一个静态域nextId:

class Employee
{
private static int nextId = 1;
private int id;
. . .
}

换句话说,如果有1000个Emplyee对象,那么就有1000个id实例域,但却只有一个nextId静态域。即使没有实例对象时,静态域也是存在的,它是属于类,而不是属于对象。

静态方法同理。

 

方法参数:

 Java中的参数是一种值引用。

首先,观察一下基本数据类型(数字、布尔值)。

public static void tripleValue(double x) // doesn't work
{
x = 3 * x;
}
double percent = 10;
tripleValue(percent);

当我们将percent作为参数给一个方法时,经过执行后,percent本身并没有改变,这个很容易理解。

接下来看一下对象引用:

public static void tripleSalary(Employee x) // works
{
x.raiseSalary(200);
}

当调用如下语句时:

harry = new Employee(. . .);
tripleSalary(harry);

具体的操作过程如下:

1.x被初始化harry值的拷贝,这是一个对象的引用。

2.raiseSalary方法应用于这个对象的引用,x和harry同时引用的那个Employee对象的薪金提高了200%。

3.方法结束后,参数变量x不再使用。当然,对象变量harry继续引用那个薪金增3倍的对象。

看到这里,或许会认为Java的对象参数是引用调用,实际上,并不是。

依然是按值调用,传给tripleSalary函数的实际上是harry值的拷贝,而harry值指向了一个对象引用,所以x也指向了该引用,所以才会引起变化。

可以通过下面这个例子得出结果:

public static void swap(Employee x, Employee y) // doesn't work
{
Employee temp = x;
x = y;
y = temp;
}

如果Java是按引用调用的话,那么执行下面语句后,a与b应该互换。

Employee a = new Employee("Alice", . . .);
Employee b = new Employee("Bob", . . .);
swap(a, b);
// does a now refer to Bob, b to Alice?

但在测试中,并没有互换,所以传入的实际上是a,b的拷贝,也就是一个对象引用,这个方法交换的是这两个拷贝。

最终,函数结束时,变量x,y被丢弃了,原来的ab对象变量依然引用之前的对象。

Java核心技术 对象与类的更多相关文章

  1. Java常见对象Object类中的个别方法

    Java常见对象Object类 public int hashCode() : 返回该对象的哈希码值. 注意:哈希值是根据哈希算法计算出来的一个值,这个值和地址值有关,但是不是实际地址值.你可以理解成 ...

  2. 快乐编程大本营【java语言训练班】 6课:用java的对象和类编程

    快乐编程大本营[java语言训练班] 6课:用java的对象和类编程 第1节. 什么是对象和类 第2节. 对象的属性和方法 第3节. 类的继承 第4节. 使用举例:创建类,定义方法,定义属性 第5节. ...

  3. Java的对象与类,继承

    Java的对象与类,继承 题目1.Java类的建立与使用 设计一个用来描述汽车的类,使用类的非静态成员变量来表示汽车的车主姓名.当前的速率和当前方向盘的转向角度,使用类的非静态成员方法来表示改变汽车的 ...

  4. 你真的了解JAVA中对象和类、this、super和static关键字吗

    作者:小牛呼噜噜 | https://xiaoniuhululu.com 计算机内功.JAVA底层.面试相关资料等更多精彩文章在公众号「小牛呼噜噜 」 目录 Java对象究竟是什么? 创建对象的过程 ...

  5. (转)java 多线程 对象锁&类锁

    转自:http://blog.csdn.net/u013142781/article/details/51697672 最近工作有用到一些多线程的东西,之前吧,有用到synchronized同步块,不 ...

  6. Java基础-对象与类

    面向对象程序设计概述 面向对象的程序设计(简称OOP)时当今主流的程序设计范型,已经取代了"结构化"过程化程序设计开发技术,Java是完全面向对象的. 类 类设计构造对象的模板或蓝 ...

  7. Java 2-Java 对象和类

    Java 对象和类 Java作为一种面向对象语言.支持以下基本概念: 多态 继承 封装 抽象 类 对象 实例 方法 消息解析 本节我们重点研究对象和类的概念. 对象:对象是类的一个实例,有状态和行为. ...

  8. Java 的对象和类

    Java 是一种面向对象的语言.作为一个面向的语言,Java 具有面向对象的特性,Java 能够支持下面的一些基本概念 − 多态(Polymorphism) 继承(Inheritance) 封装(En ...

  9. mongodb中Gson和java##Bean对象转化类

    此类使用感觉比较繁琐, 每个字段加注解才可以使用, 不如mongoTemplate使用方便, 但如果使用mongo客户端的话, 还是比手动拼接快一点, 所以贴在这儿 package com.iwher ...

随机推荐

  1. spring BeanPostProcessor

    BeanPostProcessor spring使用BeanPostProcessor接口来处理生命周期的回调 BeanPostProcessor接口定义的两个方法,分别在bean的(实例化配置和初始 ...

  2. 计算机网络四:网卡与MAC地址

    网卡与MAC地址 ㈠网卡 1.网卡定义 网卡是工作在OSI的数据链路层的网络组件,是局域网中连接计算机和传输介质(网线或WIFI信号)的接口,不仅能实现与局域网传输介质之间的物理连接和电信号匹配,还涉 ...

  3. OC重写init方法

    在创建一个对象的时候我们经常会用到init方法,单单是init只能是初始化,当我们在初始化的时候想要给这个对象加上默认的东西的时候, 系统提供的init方法就不能满足我们的需要,这时,就需要我们自己去 ...

  4. 安装kylin的艰难历程

    前言:暑假里老师布置的任务没有完成,来到学校后马不停蹄的安装kylin,结果一路艰难险阻,搞了快两个星期都没有弄好....现在止步于hive阶段卡死...仅将之前的步骤记录下来以便重新安装时更加顺利. ...

  5. SVN完全备份,增量备份,库同步

    svn备份一般采用三种方式:1)svnadmin dump 2)svnadmin hotcopy 3)svnsync. 优缺点分析: ============== 第一种svnadmin hotcop ...

  6. 关于浏览器跨域的一种实现--jsonp

    最近一直在搞python,前端技术荒废很久了,今天跟前端联调,设计到一个前端跨域的问题:前端人员告诉我可以用jsonp的方式实现,经他这么一提醒,也是豁然开朗. jsonp的实现方式我按照我的理解说一 ...

  7. Jquery中attr()与prop()的区别

    在jQuery中,attr()函数和prop()函数都用于设置或获取指定的属性,它们的参数和用法也几乎完全相同.但是,这两个函数的用处却并不相同.下面我们来详细介绍这两个函数之间的区别. 1.操作对象 ...

  8. 吴恩达机器学习笔记49-主成分分析问题(Principal Component Analysis Problem Formulation)

    主成分分析(PCA)是最常见的降维算法. 在PCA 中,我们要做的是找到一个方向向量(Vector direction),当我们把所有的数据都投射到该向量上时,我们希望投射平均均方误差能尽可能地小.方 ...

  9. JavaScript中+操作符的特殊性

    在JavaScript中+操作符有两个作用: (1)加法运算 (2)字符串连接 在使用+操作符进行运算时,当+操作符两边都是数值类型的时候,进行加法运算; 当+操作符两边有任意一边是字符串,则进行字符 ...

  10. Inotify+Rsync实现Linux服务器文件同步

    做这个功能的时候遇到了好多坑,在此感谢一下这篇博客 http://kerry.blog.51cto.com/172631/734087/  ,大家参照这篇博客就能实现该功能. 另外如果想详细了解一下的 ...