`
bolange
  • 浏览: 27077 次
  • 性别: Icon_minigender_1
  • 来自: 福州
社区版块
存档分类
最新评论

Object

    博客分类:
  • Java
阅读更多
java.lang.Object类是所有Java类的最高层次父类,该类中没有定义任何属性,方法也只有几个,但正是这些方法提供了面向对象编程技术的基本机制,下面将分别介绍:

1、hashCode()方法

hashCode()方法的格式如下:
Java代码 复制代码
  1. public int hashCode()  
public int hashCode()

其功能是返回当前对象的哈希码(HashCode)数值,哈希码可以理解为系统为每个Java对象自动创建的整型编号,任何两个不同的Java对象的哈希码一定不同,而在Java应用程序的一次执行期间,在同一个对象上多次调用hashCode()方法时,必须一致的返回相同的整数。这样哈希码就可以起到标识对象的功能,引用类型变量所记录的对象句柄实际上就包含了该对象的哈希码信息。例如:测试hashCode()方法
源文件:Person.java
Java代码 复制代码
  1. public class Person{   
  2.     private int age;   
  3.     public Person(int age){   
  4.         this.age = age;   
  5.     }   
  6.     public void setAge(int age){   
  7.         this.age = age;   
  8.     }   
  9.     public int getAge(){   
  10.         return age;   
  11.     }   
  12. }  
public class Person{
	private int age;
	public Person(int age){
		this.age = age;
	}
	public void setAge(int age){
		this.age = age;
	}
	public int getAge(){
		return age;
	}
}

源文件:TestHashCode.java
Java代码 复制代码
  1. public class TestHashCode{   
  2.     public static void main(String args[]){   
  3.         Person p1 = new Person(18);   
  4.         Person p2 = new Person(18);   
  5.         int handle1 = p1.hashCode();   
  6.         System.out.println(handle1);   
  7.         System.out.println(Integer.toHexString(handle1));   
  8.         System.out.println(p1);   
  9.         System.out.println("------------");   
  10.         System.out.println(p2.hashCode());   
  11.     }   
  12. }  
public class TestHashCode{
	public static void main(String args[]){
		Person p1 = new Person(18);
		Person p2 = new Person(18);
		int handle1 = p1.hashCode();
		System.out.println(handle1);
		System.out.println(Integer.toHexString(handle1));
		System.out.println(p1);
		System.out.println("------------");
		System.out.println(p2.hashCode());
	}
}

程序运行结果如下:
374283533
164f1d0d
Person@164f1d0d
------------
603737068

程序中,变量p1和p2所引用的两个Person类型对象虽然内容相同(属性age的值相同),但其哈希码不同,且保存在不同的空间中。还可看出,使用System.out.println()方法直接打印引用类型数据时输出的信息中包含了对象的哈希码信息,这一点在下面的toString()方法中会做解释。

2、toString()方法

Object类中toString()方法的原始定义如下:
Java代码 复制代码
  1. public String toString (){   
  2.     return getClass().getName()+”@”+Integer.toHexString(hashCode());   
  3. }  
public String toString (){
	return getClass().getName()+”@”+Integer.toHexString(hashCode());
}

该方法以字符串形式返回当前对象的有关信息,从其原始定义可以看出,所返回的是对象所属的类型名称及其哈希码。当使用System.out.println()方法直接打印输出引用类型变量时,println()方法中会自动调用其toString()方法,再将所返回的字符串信息输出到屏幕上。
如:
Java代码 复制代码
  1. System.out.println(p1);  
System.out.println(p1);

等价于:
Java代码 复制代码
  1. System.out.println(p1.toString());  
System.out.println(p1.toString());

由于Java语言中允许子类对父类中继承来的方法进行重写,以改变其实现细节,因此我们也可以根据需要在自己定义的Java类中重写其toString()方法,以提供更适合的说明信息。
例如:重写toString()方法
源文件:Person.java
Java代码 复制代码
  1. public class Person{   
  2.     private int age;   
  3.     public Person(int age){   
  4.         this.age = age;   
  5.     }   
  6.     public void setAge(int age){   
  7.         this.age = age;   
  8.     }   
  9.     public int getAge(){   
  10.         return age;   
  11.     }   
  12.     public String toString(){   
  13.         return "This is a instance of Person,age=" + age;   
  14.     }   
  15. }  
public class Person{
	private int age;
	public Person(int age){
		this.age = age;
	}
	public void setAge(int age){
		this.age = age;
	}
	public int getAge(){
		return age;
	}
	public String toString(){
		return "This is a instance of Person,age=" + age;
	}
}

源文件:TestOverride.java
Java代码 复制代码
  1. public class TestOverride{   
  2.     public static void main(String args[]){   
  3.         Person p1 = new Person(18);   
  4.         System.out.println(p1.hashCode());   
  5.         System.out.println(p1); //等价于   
  6.         System.out.println(p1.toString());    
  7.     }   
  8. }  
public class TestOverride{
	public static void main(String args[]){
		Person p1 = new Person(18);
		System.out.println(p1.hashCode());
		System.out.println(p1);	//等价于
		System.out.println(p1.toString()); 
	}
}

程序运行结果如下:
374283533
This is a instance of Person,age=18
This is a instance of Person,age=18

回想一下,我们以前使用System.out.println()方法直接打印输出java.lang.Stringjava.util.Data等类型数据时输出的也不是对象的哈希码,而是更有意义的字符串信息,原理也是相同的——这些类中也根据需要重写了各自的toString()方法。

3、equals()方法

Object类中equals()方法的原始定义如下:
Java代码 复制代码
  1. public boolean equals(Object obj){   
  2.     return (this==obj);   
  3. }  
public boolean equals(Object obj){
	return (this==obj);
}

其功能是比较当前对象和方法参数obj所引用的对象两者的等价性,如果等价则返回值为true,否则返回false。在进一步讲解之前,让我们先明确Java语言中的等价性标准:基本类型数据比较的是数据的值,而引用数据类型比较的则是对象的句柄,即对象的hashCode编码或者说引用类型变量的值,而非对象本身。简单地说,比较的永远是变量的值是否相等。
例如:“==”和equals()方法使用举例1
源文件:Person.java
Java代码 复制代码
  1. public class Person{   
  2.     private int age;   
  3.     public Person(int age){   
  4.         this.age = age;   
  5.     }   
  6.     public void setAge(int age){   
  7.         this.age = age;   
  8.     }   
  9.     public int getAge(){   
  10.         return age;   
  11.     }   
  12. }  
public class Person{
	private int age;
	public Person(int age){
		this.age = age;
	}
	public void setAge(int age){
		this.age = age;
	}
	public int getAge(){
		return age;
	}
}

源文件:TestEquals1.java
Java代码 复制代码
  1. public class TestEquals1{   
  2.     public static void main(String args[]){   
  3.         int i = 5;   
  4.         int j = 5;   
  5.         System.out.println(i == j);   
  6.         Person p1 = new Person(18);   
  7.         Person p2 = new Person(18);   
  8.         System.out.println(p1 == p2);   
  9.         System.out.println(p1.equals(p2));   
  10.         p2 = p1;   
  11.         System.out.println(p2 == p1);   
  12.         System.out.println(p1.equals(p2));   
  13.     }   
  14. }  
public class TestEquals1{
	public static void main(String args[]){
		int i = 5;
		int j = 5;
		System.out.println(i == j);
		Person p1 = new Person(18);
		Person p2 = new Person(18);
		System.out.println(p1 == p2);
		System.out.println(p1.equals(p2));
		p2 = p1;
		System.out.println(p2 == p1);
		System.out.println(p1.equals(p2));
	}
}

程序运行结果如下:
true
fals
fals
true
true

可以看出比较引用类型数据的等价性时,其标准比较苛刻,只有当两个引用变量的值相等,实际上是指向同一个对象时才算做等价。看起来使用“==”运算符与equals()方法效果似乎相同,而前者还能够判断基本数据类型数据的等价性,那么equals()方法就显得多余了,其实不然,equals()方法在比较一些特定的引用类型(如java.lang.String、java.io.File、java.util.Date以及封装类)数据时,允许改变先前严格的等价性标准——只有两个对象同为上述的特例类型且其内容相同(对象各自封装的属性值对应相同),equals()方法即判为等价,而“==”判断则不存在任何“变通”的可能。
例如:“==”和equals()方法使用举例2
Java代码 复制代码
  1. public class TestEquals2{   
  2.     public static void main(String args[]){   
  3.         String s1 = new String("abc");   
  4.         String s2 = new String("abc");   
  5.         System.out.println(s1 == s2);   
  6.         System.out.println(s1.equals(s2));   
  7.         s2 = s1;   
  8.         System.out.println(s1 == s2);   
  9.         System.out.println(s1.equals(s2));   
  10.     }   
  11. }  
public class TestEquals2{
	public static void main(String args[]){
		String s1 = new String("abc");
		String s2 = new String("abc");
		System.out.println(s1 == s2);
		System.out.println(s1.equals(s2));
		s2 = s1;
		System.out.println(s1 == s2);
		System.out.println(s1.equals(s2));
	}
}

程序运行结果如下:
false
true
true
true

之所以这样处理,是因为在实际应用开发中,人们更关心的常常是两个字符串的内容是否相同,比如身份验证时输入的用户名/密码等是否与数据库中读取出来的注册信息相匹配,而不在乎是否是同一个对象,而文件的名称和存储路径以及时间等信息的性质也是如此。需要特别说明的是,String常量内容相同的话,在内存中将只保存一份
例如:
Java代码 复制代码
  1. String s1 = "abc";   
  2. String s2 = "abc";   
  3. System.out.println(s1 == s2);   
  4. System.out.println(s1.equals(s2));  
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));

运行结果都为“true”。
其实,要实现上述“特例”并不困难,只需在Object的子类中重写其equals()方法,给出用户定义的等价性标准就是了,我们也可以在应用开发时根据需要进行类似处理。
例如:用户自定义等价性标准
源文件:Person1.java
Java代码 复制代码
  1. public class Person1{   
  2.     private int age;   
  3.     public Person1(int age){   
  4.         this.age = age;   
  5.     }   
  6.     public void setAge(int age){   
  7.         this.age = age;   
  8.     }   
  9.     public int getAge(){   
  10.         return age;   
  11.     }   
  12.     public boolean equals(Object o){   
  13.         if(o instanceof Person1){   
  14.             Person1 p = (Person1)o;   
  15.             if(this.age == p.age){   
  16.                 return true;   
  17.             }   
  18.             else  
  19.                 return false;   
  20.         }   
  21.         return false;   
  22.     }   
  23. }  
public class Person1{
	private int age;
	public Person1(int age){
		this.age = age;
	}
	public void setAge(int age){
		this.age = age;
	}
	public int getAge(){
		return age;
	}
	public boolean equals(Object o){
		if(o instanceof Person1){
			Person1 p = (Person1)o;
			if(this.age == p.age){
				return true;
			}
			else
				return false;
		}
		return false;
	}
}

源文件:TestEquals3.java
Java代码 复制代码
  1. public class TestEquals3{   
  2.     public static void main(String args[]){   
  3.         Person1 p1 = new Person1(18);   
  4.         Person1 p2 = new Person1(18);   
  5.         System.out.println(p1 == p2);   
  6.         System.out.println(p1.equals(p2));   
  7.     }   
  8. }  
public class TestEquals3{
	public static void main(String args[]){
		Person1 p1 = new Person1(18);
		Person1 p2 = new Person1(18);
		System.out.println(p1 == p2);
		System.out.println(p1.equals(p2));
	}
}

程序运行结果如下:
false
true

上述程序中Person1类中重写了equals()方法,重新定义了Person1类型数据的等价性判定标准——只要对象均为Person1类型且其age属性值相等,则认为等价,无论是否为同一个对象。其equals()方法体中的代码也可简化为:
Java代码 复制代码
  1. if(o instanceof Person1){   
  2.             Person1 p = (Person1)o;   
  3.             if(this.age == p.age)   
  4.                 return true;   
  5.         }   
  6.         return false;  
if(o instanceof Person1){
			Person1 p = (Person1)o;
			if(this.age == p.age)
				return true;
		}
		return false;

或者:
Java代码 复制代码
  1. return (o instanceof Person1)&&(((Person1)o)age == this.age);  
return (o instanceof Person1)&&(((Person1)o)age == this.age);


4、finalize()方法

Java运行时环境中的垃圾收集器在销毁一个对象之前,会自动调用该对象的finalize()方法,然后才释放对象的内存空间,该方法在Object类中的原始定义如下:
Java代码 复制代码
  1. protected void finalize() throws Throwable{}  
protected void finalize() throws Throwable{}

请注意,这里finalize()方法修饰符是protected,而不是public,这种访问控制等级使得在外界(子类以外的范围)对于该方法是不可见的,相信读者能够理解,要使其发挥作用,应该在子类中重写finalize()方法,而且,重写方法的修饰符应改为public,否则重写仍然没有实际意义。finalize()方法的用途是在子类中重写,以加入所需的逻辑代码来配置系统资源或执行其他清除操作。
例如:
源文件:Person2.java
Java代码 复制代码
  1. public class Person2{   
  2.     private String name;   
  3.     public Person2(String name){   
  4.         this.name = name;   
  5.         System.out.println("创建Person2对象,name:"+name);   
  6.     }   
  7.     public void fianlize(){   
  8.         System.out.println("销毁Person2对象,name:"+name);   
  9.     }   
  10. }  
public class Person2{
	private String name;
	public Person2(String name){
		this.name = name;
		System.out.println("创建Person2对象,name:"+name);
	}
	public void fianlize(){
		System.out.println("销毁Person2对象,name:"+name);
	}
}

源文件:TestFinalize.java
Java代码 复制代码
  1. public class TestFinalize{   
  2.     public static void main(String args[]){   
  3.         for(int i = 0;i < 10;i ++){   
  4.             Person2 p = new Person2("Tom" + i);   
  5.             for(int j = 0;j < 1000;j ++){   
  6.                 String[] test = {new String("abc"),new String("def"),new String("ghi")};   
  7.             }   
  8.         }   
  9.     }   
  10. }  
public class TestFinalize{
	public static void main(String args[]){
		for(int i = 0;i < 10;i ++){
			Person2 p = new Person2("Tom" + i);
			for(int j = 0;j < 1000;j ++){
				String[] test = {new String("abc"),new String("def"),new String("ghi")};
			}
		}
	}
}

程序运行的类似结果如下(程序每次运行的结果可能不一样,内存不同的机器运行结果也是不一样的):
创建Person2对象,name:Tom0
创建Person2对象,name:Tom1
创建Person2对象,name:Tom2
创建Person2对象,name:Tom3
创建Person2对象,name:Tom4
创建Person2对象,name:Tom5
创建Person2对象,name:Tom6
创建Person2对象,name:Tom7
销毁Person2对象,name:Tom6
销毁Person2对象,name:Tom5
创建Person2对象,name:Tom8
创建Person2对象,name:Tom9

程序中的内层for循环起到消耗内存空间的作用,读者可能奇怪为什么创建10个Person2类的对象,却只销毁了其中两个,其实Java虚拟机的垃圾回收操作对于应用程序而言是完全透明的——程序无法预料或精确控制某个无用对象何时被销毁,也就无法控制其的finalize()方法的调用时机,而且,除非垃圾回收器认为程序的可用内存空间已经不足,否则它不会试图释放无用对象占用的内存的内存。换句话说,下述情况是完全可能发生的:一个程序只占用了少量的内存,于是垃圾回收器没有在程序运行的过程中销毁无用对象并释放它们所占用的内存,也就没有调用过这些对象的finalize()方法,程序就终止了。不必担心,JVM最终关闭时还是会释放其所占用的所有内存空间。
由于finalize()方法最终是否会执行,以及何时会执行都是不确定的,在应用程序层面无法精确控制和干预,即使在应用程序中显式调用System.gc()或Runtime.gc()方法强制系统清理无用内存空间,也不能保证这一点,因此finalize()方法并不可靠,在应用程序开发中不建议使用。

5、clone()方法

在应用开发过程中,我们可能会需要拷贝(copy,复制)一个现有的对象,即得到一个新对象并希望其与现有对象封装完全相同的信息(属性值),主要是为了此后两者互不相干,修改其中的一个对象不会影响到另一个,我们知道,简单地进行引用变量间的赋值是不能解决问题的,因为并没有创建新对象;而自己编写代码先创建一个新对象,再将原始对象的属性值一一复制过来也比较烦琐,且存在后述的“浅度拷贝”问题;这种情况下,利用clone()方法来实现对象拷贝不失为一种明智的选择。
Object类中的clone()方法专门提供拷贝当前对象的功能,其原型如下:
Java代码 复制代码
  1. protected native Object clone() throws CloneNotSupportedException;  
protected native Object clone() throws CloneNotSupportedException;

其中的修饰符native标明此方法是一个本地方法,即调用了其运行时所在平台/操作系统的底层功能,当然这是早就实现好的,读者不必为此分心。该方法能够创建并返回当前对象的一个副本,可以理解为将当前对象的所有信息(一段连续的内存空间中存储的数据)直接复制一份并单独保存,因此其返回的是已经包含了原有对象信息的一个新对象,而不是原有对象的引用。
和finalize()方法类似,clone()方法在Object类中也被定义为protected的,因此只有在其子类中进行重写才能真正发挥作用,Java语言规定,所有要进行“克隆”的对象所属的类必须实现java.lang.Cloneable接口,这是一种安全性保护。
例如:实现简单的克隆操作
源文件:Person3.java
Java代码 复制代码
  1. public class Person3 implements Cloneable{   
  2.     private String name;   
  3.     private int age;   
  4.     public Person3(String name,int age){   
  5.         this.name = name;   
  6.         this.age = age;   
  7.     }   
  8.     public void setName(String name){   
  9.         this.name = name;   
  10.     }   
  11.     public void setAge(int age){   
  12.         this.age = age;   
  13.     }   
  14.     public String getName(){   
  15.         return name;   
  16.     }   
  17.     public int getAge(){   
  18.         return age;   
  19.     }   
  20.     public void display(){   
  21.         System.out.println("Name:"+name+"\tAge:"+age);   
  22.     }   
  23.     public Object clone(){   
  24.         Person3 p = null;   
  25.         try{   
  26.             p = (Person3)super.clone();   
  27.         }catch(CloneNotSupportedException e){   
  28.             e.printStackTrace();   
  29.         }   
  30.         return p;   
  31.     }   
  32. }  
public class Person3 implements Cloneable{
	private String name;
	private int age;
	public Person3(String name,int age){
		this.name = name;
		this.age = age;
	}
	public void setName(String name){
		this.name = name;
	}
	public void setAge(int age){
		this.age = age;
	}
	public String getName(){
		return name;
	}
	public int getAge(){
		return age;
	}
	public void display(){
		System.out.println("Name:"+name+"\tAge:"+age);
	}
	public Object clone(){
		Person3 p = null;
		try{
			p = (Person3)super.clone();
		}catch(CloneNotSupportedException e){
			e.printStackTrace();
		}
		return p;
	}
}

源文件:TestClone.java
Java代码 复制代码
  1. public class TestClone{   
  2.     public
    分享到:
    评论

相关推荐

    Delphi7用superobject解析Json数据,superobject.pas下载

    Delphi读写操作JSON字符串时,需引用一个superobject.pas文件。 var jo,jt:ISuperObject; begin jo:=SO(); jt:=SO(); jo.S['姓名']:='小王'; jo.I['年龄']:=25; jo.S['性别']:='男'; jt.O['人员']:=jo; ...

    Inside The C++ Object Model 英文版

    Inside the C++ Object Model focuses on the underlying mechanisms that support object-oriented programming within C++: constructor semantics, temporary generation, support for encapsulation, ...

    浅析C# 中object sender与EventArgs e

    public delegate void EventHandler( object sender, EventArgs e ) 注意这里的参数,前者是一个对象(其实这里传递的是对象的引用,如果是button1的click事件则sender就是button1),后面是包含事件数据的类的基类...

    Object Tracking A Survey

    Difficulties in tracking objects can arise due to abrupt object motion, changing appearance patterns of both the object and the scene, nonrigid object structures, object-to-object and object-to-scene...

    3D Object Converter V4.4 汉化版

    3D Object Converter 是一个强大的3D文件浏览及转换工具,到目前的V4.0为止它已经可以支持多达468种3D文件格式! 无论是像LWO(LightWave)、C4D(Cinema 4D)、XSI(Softimage XSI)、3DM(Rhinoceros)、LXO...

    控制台报错object is not a function的解决方法

    打开控制台发现报错:object is not a function。 感觉很奇怪,这块的功能最新没动过怎么会突然出问题了呢?上线时主流浏览器都测试过了呀。 虽然奇怪,但是还的解决问题。看着代码发现一个radio对象的name属性和一...

    c# win7使用Micosoft Speech Object Library示例

    Micosoft Speech Object Library[Version5.1]的ActiveX组件,将它导入。 你会看到一大堆控件,不过你要用的只是TSpVoice而已。 TSpVoice实现了对SAPI的包装,能够设置Rate(音速), volume(音量), 当然还有...

    Object Thingking 英文文字版pdf

    object thinking 英文高清原版文字版 pdf In OBJECT THINKING, esteemed object technologist David West contends that the mindset makes the programmer—not the tools and techniques. Delving into the ...

    Beginning.Object-Oriented.Programming.with.C#

    中文名: Beginning C# Object-Oriented Programming (第1版, 涵盖.NET 4.0 and C# 4.0) 原名: Beginning C# Object-Oriented Programming, 1st edition 作者: Dan Clark 资源格式: PDF 出版社: Apress书号: 978-...

    Delphi x-superobject 跨平台的JSON处理单元andriod ios可用

    原来用的superobject在windows下没问题,转android之后发现不能编译,因为包含的TSuperArray是class类型,不能包含在record,后来找了这个跨平台的版本;但是会有一些问题,当读取的json值不确定时,会出现type cast...

    Object Detection with Discriminatively Trained Part-Based Models

    We describe an object detection system based on mixtures of multiscale deformable part models. Our system is able to represent highly variable object classes and achieves state-of-the-art results in ...

    ScriptableObject.zip

    一个关于Unity的ScriptableObject类的简要小例子,作为记录!

    SI Object Brower 10破解版

    SI Object Brower 10破解版

    ldap提示object class violation

    ldap提示object class violation

    object中toString方法简介_动力节点Java学院整理.doc

    Object类在Java里面是一个比较特殊的类,JAVA只支持单继承,子类只能从一个父类来继承,如果父类又是从另外一个父类继承过来,那他也只能有一个父类,父类再有父类,那也只能有一个,JAVA为了组织这个类组织得比较...

    xml2object、object2xml之JAXB

    前段时间找了好久xml与object之间的转换都没找到!最近在学习WebService,讲到JAXB!没听说过!看了才知道jdk中自带了这个功能,什么这个框架那个框架都用了!原来就在眼前你也不知道!我这儿有视频,有需要请留言!...

    托盘,右键演示,C#源代码private void Form1_Load(object sender, EventArgs e)

    托盘,右键演示,C#源代码private void Form1_Load(object sender, EventArgs e) {//设置托盘控件属性 this.notifyIcon1.ContextMenuStrip = this.contextMenuStrip1; this.notifyIcon1.Text = "演示创建托盘"; ...

    Inside C++ Object Model

    Inside C++ Object Model/Inside C++ Object Model/Inside C++ Object Model/Inside C++ Object Model

    对象 Object 转换工具

    使用此工具类,对于Object和byte[] 数组, 16进制和String之间的转换

    SuperObject增加排序.rar

    开源的SuperObject基础上增加排序,并且不影响性能,原SuperObject属性顺序随机,看着比较累。 DelphiXE的项目中已经使用,非常方便

Global site tag (gtag.js) - Google Analytics