- 浏览: 280704 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (133)
- GWT (7)
- IT生活 (9)
- JAVA综合 (38)
- Servlet (5)
- vaadin (2)
- About Eclipse (2)
- StarUML (1)
- Spring (7)
- ibatis (3)
- web (35)
- ExtJs (2)
- Quartz (13)
- Struts (1)
- 学习XML (6)
- io流 (2)
- web应用之压缩 (3)
- Spring MVC (0)
- Velocity (5)
- 静态代码分析工具 (2)
- 观点 (1)
- JUnit (3)
- jQuery (4)
- mysql (2)
- javascript (16)
- linux (4)
- pattern (1)
- java加密技术 (2)
最新评论
-
tan4836128:
确实不行,我的1.8.5,降到1.6.2也不行,楼主的情况很局 ...
Spring调用Quartz定时任务报Couldn't store trigger异常 -
alfusen_xiong:
有没有自动注入的方法可以取代executeInternal() ...
Quartz任务中调用Spring容器中bean及动态调度任务 -
luoxiang183:
换了也不行啊
Spring调用Quartz定时任务报Couldn't store trigger异常 -
liubey:
首先谢谢LZ的文章,其实我想问个问题,既然有心做成工具类,就最 ...
对象和map转换 -
小林夕:
几年前用还行,现在做UML一般都开始使用在线作图工具了,可以了 ...
StarUML简介
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.String、java.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 static void main(String args[]){
3. Person3 p1 = new Person3("Tom",18);
4. Person3 p2 = (Person3)p1.clone();
5. System.out.println(p1 == p2);
6. System.out.println(p1.equals(p2));
7. p2.setAge(25);
8. p2.display();
9. p1.display();
10. }
11.}
public class TestClone{
public static void main(String args[]){
Person3 p1 = new Person3("Tom",18);
Person3 p2 = (Person3)p1.clone();
System.out.println(p1 == p2);
System.out.println(p1.equals(p2));
p2.setAge(25);
p2.display();
p1.display();
}
}
程序运行结果如下:
false
false
Name:Tom Age:25
Name:Tom Age:18
查看java.lang.Cloneable接口大源代码,你会发现该接口中没有任何内容,其源代码如下:
Java代码
1.package java.lang;
2.public interface Cloneable(){
3.}
package java.lang;
public interface Cloneable(){
}
这样的接口被称为空接口,实际上只是起到标识的作用——必须是该接口实现类的实例才能进行克隆操作,因此这样的接口也称“标记性接口”。
需要小心的是,使用上述的clone()方法进行对象拷贝可能出现“浅度拷贝”(Low Copy)的问题。
例如:浅度拷贝
源文件:Person3.java
源文件:Book.java
Java代码
1.public class Book implements Cloneable{
2. String bookName;
3. double price;
4. Person3 author;
5. public Book(String bn,double p,Person3 a){
6. bookName = bn;
7. price = p;
8. author = a;
9. }
10. public Object clone(){
11. Book b = null;
12. try{
13. b = (Book)super.clone();
14. }catch(CloneNotSupportedException e){
15. e.printStackTrace();
16. }
17. return b;
18. }
19. public void display(){
20. System.out.println(bookName+"\t"+price+"\t");
21. author.display();
22. }
23.}
public class Book implements Cloneable{
String bookName;
double price;
Person3 author;
public Book(String bn,double p,Person3 a){
bookName = bn;
price = p;
author = a;
}
public Object clone(){
Book b = null;
try{
b = (Book)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return b;
}
public void display(){
System.out.println(bookName+"\t"+price+"\t");
author.display();
}
}
源文件:TestLowCopy.java
Java代码
1.public class TestLowCopy{
2. public static void main(String args[]){
3. Book b1 = new Book("Java编程思想",99,new Person3("张三",48));//p0
4. Book b2 = (Book)b1.clone();//p1
5. b2.bookName = "Java核心技术";//p2
6. b2.price = 100;
7. b2.author.setName("李四");
8. b2.author.setAge(36);
9. b1.display();
10. b2.display();
11. }
12.}
public class TestLowCopy{
public static void main(String args[]){
Book b1 = new Book("Java编程思想",99,new Person3("张三",48));//p0
Book b2 = (Book)b1.clone();//p1
b2.bookName = "Java核心技术";//p2
b2.price = 100;
b2.author.setName("李四");
b2.author.setAge(36);
b1.display();
b2.display();
}
}
程序运行结果如下:
Java编程思想 99.0
Name:李四 Age:36
Java核心技术 100.0
Name:李四 Age:36
可以看出克隆后b2对象对其属性author所引用的Person对象的改动影响到了b1,这是由clone()方法的实现机制决定的——clone()方法先在内存中开辟一块目标对象所需的存储空间(只要是同属于一个类型,则对象占有的存储空间大小也一定相同),然后直接将原始对象存储空间中的内容(包括各属性的值)原样拷贝过来。对基本类型的属性,其属性值就是真正要用的信息,这样的操作当然没有问题,但对于引用类型的属性,其值只是所引用的其他对象的句柄,这就导致clone后“副本”对象与原始对象的引用类型属性指向同样的对象,为更直观,现给出上述程序运行到关键点时的内存状态。如图1~3:
这种不够彻底的拷贝也称浅度拷贝,浅度拷贝可能造成“原件”和“副本”对象之间的“藕断丝连”,往往导致我们所不希望的结果。与之相应的彻底拷贝操作被称为“深度拷贝”(Deep Copy),实现起来也不算困难,只需在拷贝目标对象时对与其有关联的对象,比如上例中要拷贝的Book对象通过其属性author所引用的Person3对象,也同时进行显式拷贝处理。
例如:深度拷贝
源文件:Person3.java
源文件:Book1.java
Java代码
1.public class Book1 implements Cloneable{
2. String bookName;
3. double price;
4. Person3 author;
5. public Book1(String bn,double p,Person3 a){
6. bookName = bn;
7. price = p;
8. author = a;
9. }
10. public Object clone(){
11. Book1 b = null;
12. try{
13. b = (Book1)super.clone();
14. }catch(CloneNotSupportedException e){
15. e.printStackTrace();
16. }
17. b.author = (Person3)author.clone();
18. return b;
19. }
20. public void display(){
21. System.out.println(bookName+"\t"+price+"\t");
22. author.display();
23. }
24.}
public class Book1 implements Cloneable{
String bookName;
double price;
Person3 author;
public Book1(String bn,double p,Person3 a){
bookName = bn;
price = p;
author = a;
}
public Object clone(){
Book1 b = null;
try{
b = (Book1)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
b.author = (Person3)author.clone();
return b;
}
public void display(){
System.out.println(bookName+"\t"+price+"\t");
author.display();
}
}
源文件:TestDeepCopy.java
Java代码
1.public class TestDeepCopy{
2. public static void main(String args[]){
3. Book1 b1 = new Book1("Java编程思想",99,new Person3("张三",48));
4. Book1 b2 = (Book1)b1.clone();
5. b2.bookName = "Java核心技术";
6. b2.price = 100;
7. b2.author.setName("李四");
8. b2.author.setAge(36);
9. b1.display();
10. b2.display();
11. }
12.}
public class TestDeepCopy{
public static void main(String args[]){
Book1 b1 = new Book1("Java编程思想",99,new Person3("张三",48));
Book1 b2 = (Book1)b1.clone();
b2.bookName = "Java核心技术";
b2.price = 100;
b2.author.setName("李四");
b2.author.setAge(36);
b1.display();
b2.display();
}
}
程序运行结果如下:
Java编程思想 99.0
Name:张三 Age:48
Java核心技术 100.0
Name:李四 Age:36
Object类中的wait()和notify()等方法也很有用,专门用于多线程编程中的线程同步性处理
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.String、java.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 static void main(String args[]){
3. Person3 p1 = new Person3("Tom",18);
4. Person3 p2 = (Person3)p1.clone();
5. System.out.println(p1 == p2);
6. System.out.println(p1.equals(p2));
7. p2.setAge(25);
8. p2.display();
9. p1.display();
10. }
11.}
public class TestClone{
public static void main(String args[]){
Person3 p1 = new Person3("Tom",18);
Person3 p2 = (Person3)p1.clone();
System.out.println(p1 == p2);
System.out.println(p1.equals(p2));
p2.setAge(25);
p2.display();
p1.display();
}
}
程序运行结果如下:
false
false
Name:Tom Age:25
Name:Tom Age:18
查看java.lang.Cloneable接口大源代码,你会发现该接口中没有任何内容,其源代码如下:
Java代码
1.package java.lang;
2.public interface Cloneable(){
3.}
package java.lang;
public interface Cloneable(){
}
这样的接口被称为空接口,实际上只是起到标识的作用——必须是该接口实现类的实例才能进行克隆操作,因此这样的接口也称“标记性接口”。
需要小心的是,使用上述的clone()方法进行对象拷贝可能出现“浅度拷贝”(Low Copy)的问题。
例如:浅度拷贝
源文件:Person3.java
源文件:Book.java
Java代码
1.public class Book implements Cloneable{
2. String bookName;
3. double price;
4. Person3 author;
5. public Book(String bn,double p,Person3 a){
6. bookName = bn;
7. price = p;
8. author = a;
9. }
10. public Object clone(){
11. Book b = null;
12. try{
13. b = (Book)super.clone();
14. }catch(CloneNotSupportedException e){
15. e.printStackTrace();
16. }
17. return b;
18. }
19. public void display(){
20. System.out.println(bookName+"\t"+price+"\t");
21. author.display();
22. }
23.}
public class Book implements Cloneable{
String bookName;
double price;
Person3 author;
public Book(String bn,double p,Person3 a){
bookName = bn;
price = p;
author = a;
}
public Object clone(){
Book b = null;
try{
b = (Book)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return b;
}
public void display(){
System.out.println(bookName+"\t"+price+"\t");
author.display();
}
}
源文件:TestLowCopy.java
Java代码
1.public class TestLowCopy{
2. public static void main(String args[]){
3. Book b1 = new Book("Java编程思想",99,new Person3("张三",48));//p0
4. Book b2 = (Book)b1.clone();//p1
5. b2.bookName = "Java核心技术";//p2
6. b2.price = 100;
7. b2.author.setName("李四");
8. b2.author.setAge(36);
9. b1.display();
10. b2.display();
11. }
12.}
public class TestLowCopy{
public static void main(String args[]){
Book b1 = new Book("Java编程思想",99,new Person3("张三",48));//p0
Book b2 = (Book)b1.clone();//p1
b2.bookName = "Java核心技术";//p2
b2.price = 100;
b2.author.setName("李四");
b2.author.setAge(36);
b1.display();
b2.display();
}
}
程序运行结果如下:
Java编程思想 99.0
Name:李四 Age:36
Java核心技术 100.0
Name:李四 Age:36
可以看出克隆后b2对象对其属性author所引用的Person对象的改动影响到了b1,这是由clone()方法的实现机制决定的——clone()方法先在内存中开辟一块目标对象所需的存储空间(只要是同属于一个类型,则对象占有的存储空间大小也一定相同),然后直接将原始对象存储空间中的内容(包括各属性的值)原样拷贝过来。对基本类型的属性,其属性值就是真正要用的信息,这样的操作当然没有问题,但对于引用类型的属性,其值只是所引用的其他对象的句柄,这就导致clone后“副本”对象与原始对象的引用类型属性指向同样的对象,为更直观,现给出上述程序运行到关键点时的内存状态。如图1~3:
这种不够彻底的拷贝也称浅度拷贝,浅度拷贝可能造成“原件”和“副本”对象之间的“藕断丝连”,往往导致我们所不希望的结果。与之相应的彻底拷贝操作被称为“深度拷贝”(Deep Copy),实现起来也不算困难,只需在拷贝目标对象时对与其有关联的对象,比如上例中要拷贝的Book对象通过其属性author所引用的Person3对象,也同时进行显式拷贝处理。
例如:深度拷贝
源文件:Person3.java
源文件:Book1.java
Java代码
1.public class Book1 implements Cloneable{
2. String bookName;
3. double price;
4. Person3 author;
5. public Book1(String bn,double p,Person3 a){
6. bookName = bn;
7. price = p;
8. author = a;
9. }
10. public Object clone(){
11. Book1 b = null;
12. try{
13. b = (Book1)super.clone();
14. }catch(CloneNotSupportedException e){
15. e.printStackTrace();
16. }
17. b.author = (Person3)author.clone();
18. return b;
19. }
20. public void display(){
21. System.out.println(bookName+"\t"+price+"\t");
22. author.display();
23. }
24.}
public class Book1 implements Cloneable{
String bookName;
double price;
Person3 author;
public Book1(String bn,double p,Person3 a){
bookName = bn;
price = p;
author = a;
}
public Object clone(){
Book1 b = null;
try{
b = (Book1)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
b.author = (Person3)author.clone();
return b;
}
public void display(){
System.out.println(bookName+"\t"+price+"\t");
author.display();
}
}
源文件:TestDeepCopy.java
Java代码
1.public class TestDeepCopy{
2. public static void main(String args[]){
3. Book1 b1 = new Book1("Java编程思想",99,new Person3("张三",48));
4. Book1 b2 = (Book1)b1.clone();
5. b2.bookName = "Java核心技术";
6. b2.price = 100;
7. b2.author.setName("李四");
8. b2.author.setAge(36);
9. b1.display();
10. b2.display();
11. }
12.}
public class TestDeepCopy{
public static void main(String args[]){
Book1 b1 = new Book1("Java编程思想",99,new Person3("张三",48));
Book1 b2 = (Book1)b1.clone();
b2.bookName = "Java核心技术";
b2.price = 100;
b2.author.setName("李四");
b2.author.setAge(36);
b1.display();
b2.display();
}
}
程序运行结果如下:
Java编程思想 99.0
Name:张三 Age:48
Java核心技术 100.0
Name:李四 Age:36
Object类中的wait()和notify()等方法也很有用,专门用于多线程编程中的线程同步性处理
发表评论
-
mysql中varchar类型转换Integer
2011-11-24 15:22 1295CAST(varchar字段 AS SIGNED) -
java 添加和清除cookie
2011-10-24 09:38 2112//添加cookie Cookie cookie = new ... -
java cookie操作
2011-10-24 09:34 1499Cookie概念: Cookie的格式实际上是一段纯文 ... -
java保留两位小数点(转)
2011-10-19 15:48 5732java保留两位小数问题: 方式一: 四舍五入 dou ... -
ibatis中批量删除
2011-09-15 10:27 1723Ibatis中批量删除方法: 方法一: 在映射文件中,按如 ... -
Java反射getFields()和getDeclaredFields()的区别
2011-09-05 13:23 1680Java反射 getFields()和getDeclaredF ... -
AES加密算法原理
2011-09-01 15:18 1754AES加密算法原理 随 ... -
Java AES加密实例
2011-09-01 14:30 3467package com.encrypt.hello; i ... -
Quartz任务中调用Spring容器中bean及动态调度任务
2011-08-31 15:09 19830Quartz 是开源任务调度框 ... -
Observer模式
2011-08-23 09:46 1043Java深入到一定程度,就不可避免的碰到设计模式(design ... -
Java环境下Memcached应用详解(转)
2011-08-22 10:05 0本文将对在Java环境下Memcached应用进行详细介绍。M ... -
Spring容器详解(转)
2011-08-22 09:53 1293我们在使用ssh整合项目的时候,Spring在其中是一个非常重 ... -
Spring DI(依赖注入) IOC(控制反转) AOP(面向切面编程)
2011-08-22 09:43 2133spring 的优点? 1.降低了 ... -
11款用于优化、分析源代码的Java工具
2011-08-08 15:13 907本文将提供一些工具, ... -
Java编程中影响性能的一些特点
2011-08-08 15:04 782文中将提供一些在Java编程中影响性能的一些特点,为了能够提高 ... -
Velocity基础
2011-08-08 11:01 1815Velocity 基础 Velocity是一个基于java的 ... -
java io经典例子
2011-08-03 14:45 1165IO是JAVASE中非常重要的一块,是面向对象的完美体现,深入 ... -
JUnit4详细教程
2011-08-02 15:36 1242因jdk5中的新特性,JUn ... -
JUnit4注解
2011-08-02 15:31 1029JUnit4注解 JUnit4的测试类不用再继承TestCa ... -
JUnit简明手册
2011-08-02 15:29 903用XP进行开发的过程,unit test是必不可少的环节。作为 ...
相关推荐
### Object类和Scanner类 #### 一、Object类详解 **1.1 概述** 在Java语言中,`Object` 类是所有类的基础。它位于类层次结构的顶端,这意味着所有的类,无论显式还是隐式地,都直接或间接地继承自 `Object` 类。...
通过"最完整的Object Pascal语言介绍",读者将能够深入理解Object Pascal的各个方面,包括语法、面向对象编程、Delphi IDE的使用以及如何利用VCL和FireMonkey进行应用开发。无论你是初学者还是有经验的开发者,这份...
1. **Object类介绍** Object类提供了创建自定义对象的便利,避免了手动定义构造函数的复杂性。所有JavaScript对象都是Object的实例,或者是直接或间接继承自Object的实例。 2. **Object类主要属性** - `...
Excel数据解析,自动创建对应C#类,自动创建ScriptableObject生成类,自动序列化Asset文件 功能介绍链接 https://z-c-s.blog.csdn.net/article/details/125608062
Object类 getClass 马克-to-win java视频 的详细描述介绍
Object Pascal是一种基于Pascal语言的面向对象编程方言,它在Pascal的基础上添加了类、对象、接口等面向对象编程的概念,使得程序设计更加灵活和强大。这篇“最完整的Object Pascal语言介绍(中文版)”涵盖了Object ...
**Object Pascal 中文介绍** Object Pascal 是一种基于 Pascal 语言的面向对象的编程语言,它在传统的 Pascal 语言基础上增加了类、对象、继承、多态等面向对象特性。Object Pascal 最初由 Borland 公司的 Delphi ...
在文章中,作者张树彬详细介绍了SharedObject类的常用函数及其使用方法和注意事项。这为Flash开发者在进行本地数据存储和处理方面提供了专业的指导和参考。通过掌握SharedObject的使用,开发者可以更有效地实现游戏...
本篇文章将详细介绍如何将一个`object`类型的变量安全地转换为`DateTime`类型,并解释相关的代码实现细节。 #### 一、问题背景 在实际开发过程中,我们经常会遇到需要从数据库或其他数据源读取日期和时间的情况。...
Object Class概念介绍 在LDAP中,每个目录条目都有一个或多个对象类(Object Class),这些对象类定义了该条目的属性集。例如,“person”对象类定义了一个人的基本属性,如名字、姓氏等。“organizationalUnit”...
首先,我们需要创建一个ScriptableObject类来存储CSV数据。在Unity中,ScriptableObject是一种可以被保存到项目资源目录(Assets/Resources)中的脚本组件,它可以独立于任何场景存在。以下是一个简单的`soCsv`类...
`JavaScriptSerializer`是.NET Framework提供的一种用于序列化和反序列化对象为JSON格式的工具类。它可以通过将JSON字符串转换为.NET对象(如`Dictionary, object>`),从而让我们能够方便地访问这些对象的属性。 #...
Java中的Object类是所有类的根父类,无论是直接还是间接,每个Java类最终都会继承Object。这个类提供了基本的对象行为,包括数据存储、比较、复制以及与其他对象交互的能力。以下是对Object类的重要方法和特点的详细...
通过上述介绍,我们了解了Object-C中类的基本结构以及属性的声明和使用方法。在实际开发过程中,合理地利用这些概念可以帮助开发者构建出高效且易于维护的应用程序。无论是对于初学者还是有经验的开发者来说,掌握...
这份"Objective-C介绍文档20120129"是关于Objective-C编程语言的详细指南,虽然全英文可能会对阅读造成一定困扰,但它包含了丰富的知识和深入的解释。 Objective-C起源于C语言,它在C的基础上添加了面向对象的特性...
**Object Pascal编程指南** Object Pascal是一种面向对象的编程语言,它是...以上是对Object Pascal编程的一些基本概念和关键特性介绍。通过深入学习和实践,开发者可以充分利用这些工具构建高效、可维护的软件系统。
类设计的注意事项、设计模式、内部类、Object介绍、异常细节、包(package)