java小点滴
1.= = 和 equals()方法
= = 比较是否指向同一个引用,而equals()比较值
equals()原形
一个极端的类
Class Monster{
private String content;
...
boolean equals(Object another){ return true;}
}
覆盖了equals方法。这个实现会导致无论Monster实例内容如何,它们之间的比较永远返回true。
所以当用equals方法判断对象的内容是否相等,请不要想当然。因为可能认为相等,而这个类的作者不这样认为,而类的equals方法的实现是由他掌握的。如果需要使用equals方法,或者使用任何基于散列码的集合(HashSet,HashMap,HashTable),请察看一下java doc以确认这个类的equals逻辑是如何实现的。
2.String是否已经改变
String s = "Hello";
s = s + " world!";
s所指向的对象是否改变了呢?
答案是没有,因为String被设计成不可变(immutable)类,所以它的所有对象都是不可变对象.
过程:s是一个String的引用变量,它指向的内容为 "Hello",然后我们对 s (不是"Hello")进行了 + 操作,此时,s所指向的仍是一个String的变量,内容为"Hello World",而原来那个 "Hello"仍存在于内存中,只不过s不指向它了.
3.声明变量时,初始化尽量放到构造函数中,这样可以减少不必要的开支.
public class Demo {
private String s;
...
public Demo {
s = "Initial Value";
}
...
}
而非
s = new String("Initial Value");
后者每次都会调用构造器,生成新对象,性能低下且内存开销大,并且没有意义,因为String对象不可改变,所以对于内容相同的字符串,只要一个String对象来表示就可以了。也就说,多次调用上面的构造器创建多个对象,他们的String类型属性s都指向同一个对象。
上面的结论还基于这样一个事实:对于字符串常量,如果内容相同,Java认为它们代表同一个String对象。而用关键字new调用构造器,总是会创建一个新的对象,无论内容是否相同。
至于为什么要把String类设计成不可变类,是它的用途决定的。其实不只String,很多Java标准类库中的类都是不可变的。在开发一个系统的时候,我们有时候也需要设计不可变类,来传递一组相关的值,这也是面向对象思想的体现。不可变类有一些优点,比如因为它的对象是只读的,所以多线程并发访问也不会有任何问题。当然也有一些缺点,比如每个不同的状态都要一个对象来代表,可能会造成性能上的问题。所以Java标准类库还提供了一个可变版本,即StringBuffer。
3.关于toString()
每个非primitive对象都有一个toString()方法,当编译器需要一个String而它却是一个对象的时候,编译器就会自动的调用这个方法,而不需要对象类的对象.toString()调用。
可以在自己的类中重写toString()来达到此功能。
4.public static void mian(String str[]){} //方法
每个类都可以有一个 main()方法作为测试,类可以不是public,只要main()是public的就行。
当 java 类(运行此类)时 ,编绎器会自动调用 类.main()方法。
= = 比较是否指向同一个引用,而equals()比较值
equals()原形
boolean equals(Object obj)
{
return this == obj;
}
Object对象默认使用了==操作符。所以如果你自创的类没有覆盖equals方法,那你的类使用equals和使用==会得到同样的结果。同样也可以看出,Object的equals方法没有达到equals方法应该达到的目标:比较两个对象内容是否相等。因为答案应该由类的创建者决定,所以Object把这个任务留给了类的创建者。(暂时还不是太了解.){
return this == obj;
}
一个极端的类
Class Monster{
private String content;
...
boolean equals(Object another){ return true;}
}
覆盖了equals方法。这个实现会导致无论Monster实例内容如何,它们之间的比较永远返回true。
所以当用equals方法判断对象的内容是否相等,请不要想当然。因为可能认为相等,而这个类的作者不这样认为,而类的equals方法的实现是由他掌握的。如果需要使用equals方法,或者使用任何基于散列码的集合(HashSet,HashMap,HashTable),请察看一下java doc以确认这个类的equals逻辑是如何实现的。
2.String是否已经改变
String s = "Hello";
s = s + " world!";
s所指向的对象是否改变了呢?
答案是没有,因为String被设计成不可变(immutable)类,所以它的所有对象都是不可变对象.
过程:s是一个String的引用变量,它指向的内容为 "Hello",然后我们对 s (不是"Hello")进行了 + 操作,此时,s所指向的仍是一个String的变量,内容为"Hello World",而原来那个 "Hello"仍存在于内存中,只不过s不指向它了.
3.声明变量时,初始化尽量放到构造函数中,这样可以减少不必要的开支.
public class Demo {
private String s;
...
public Demo {
s = "Initial Value";
}
...
}
而非
s = new String("Initial Value");
后者每次都会调用构造器,生成新对象,性能低下且内存开销大,并且没有意义,因为String对象不可改变,所以对于内容相同的字符串,只要一个String对象来表示就可以了。也就说,多次调用上面的构造器创建多个对象,他们的String类型属性s都指向同一个对象。
上面的结论还基于这样一个事实:对于字符串常量,如果内容相同,Java认为它们代表同一个String对象。而用关键字new调用构造器,总是会创建一个新的对象,无论内容是否相同。
至于为什么要把String类设计成不可变类,是它的用途决定的。其实不只String,很多Java标准类库中的类都是不可变的。在开发一个系统的时候,我们有时候也需要设计不可变类,来传递一组相关的值,这也是面向对象思想的体现。不可变类有一些优点,比如因为它的对象是只读的,所以多线程并发访问也不会有任何问题。当然也有一些缺点,比如每个不同的状态都要一个对象来代表,可能会造成性能上的问题。所以Java标准类库还提供了一个可变版本,即StringBuffer。
3.关于toString()
每个非primitive对象都有一个toString()方法,当编译器需要一个String而它却是一个对象的时候,编译器就会自动的调用这个方法,而不需要对象类的对象.toString()调用。
可以在自己的类中重写toString()来达到此功能。
class source
{
private String s;
public source()
{
s = new String("returnSource");
}
public String toString()
{
return s;
}
}
public class toStringTest
{
source se = new source();
private String str = "aaaa";
private String str2 = "bbb";
public String toString()
{
return str + str2 + se;
}
public static void main(String[] str)
{
toStringTest tt = new toStringTest();
System.out.println(tt);
///////////// result is "aaaabbbreturnSource"
}
}
{
private String s;
public source()
{
s = new String("returnSource");
}
public String toString()
{
return s;
}
}
public class toStringTest
{
source se = new source();
private String str = "aaaa";
private String str2 = "bbb";
public String toString()
{
return str + str2 + se;
}
public static void main(String[] str)
{
toStringTest tt = new toStringTest();
System.out.println(tt);
///////////// result is "aaaabbbreturnSource"
}
}
4.public static void mian(String str[]){} //方法
每个类都可以有一个 main()方法作为测试,类可以不是public,只要main()是public的就行。
当 java 类(运行此类)时 ,编绎器会自动调用 类.main()方法。