Java笔记:包装类、toString()方法、单例类、比较(==和equals方法)
1.包装类
1)包装类为基本数据类型提供了相应的引用数据类型。
(基本数据类型-包装类)
btye-Byte,char-Character,short-Short,float-Float
int-Integer,double-Double,long-Long,boolean-Boolean
2)通过包装类的构造器来实现吧基本数据类型包装成包装类
3)可以通过使用包装类的xxxValue()实例方法,可以获得包装类对象中包装的基本数据类型。
package cn.it.lsl; public class Primitive2Wrapper { public static void main(String[] args) { boolean b = true; Boolean b1 = new Boolean(b); int a = 5; Integer a1 = new Integer(a); //把一个字符串包装成包装类 (Character类除外) Float f = new Float("2.3"); Boolean b2 = new Boolean("false"); boolean b3 = b2.booleanValue(); System.out.println(b3); int aa = a1.intValue(); System.out.println(aa); //当用一个字符串来创建Boolean对象时,如果传入的是字符串"true",或或次字符串不同字母的大小写变化形式,如"True",都将创建true对应的Boolean对象 //当传入其他字符串时,都会创建false对应的Boolean对象 Boolean b4 = new Boolean("true"); boolean b5 = b4.booleanValue(); System.out.println(b5); } }
4)以上的转换比较麻烦,在JDK1.5中提供了自动装箱和自动拆箱功能实现包装类跟基本数据类型的转换。
自动装箱:把基本数据类型直接赋值给对应的包装类
自动拆箱:把包装类直接赋值给对应的基本数据类型
eg:
Integer a = 5; int b = a;
5)包装类还可以实现基本类型和字符串之间的转换。
把字符串类型的值转换为基本类型的值
(1)利用parseXxx(String s)方法(Charcater除外)
(2)利用包转类提供的构造器
把基本类型转为字符串
(1)String类的valueOf()
(2)基本类型和""进行连接运算
package cn.it.lsl; public class Primitive2Wrapper { public static void main(String[] args) { String str = "23"; int a1 = Integer.parseInt(str); int a2 = new Integer(str); System.out.println(a1); System.out.println(a2); String str2 = String.valueOf(2.34f); System.out.println(str2); System.out.println(23+""); } }
6)包装类的比较
(1)包装类可以与基本数据类型比较
(2)因为包装类是引用数据类型,所以只有两个包装类指向用一个对象的时候才会返回true
Integer a = new Integer(6); System.out.println("6的包装类是否大于5.0:" + (a>5.0)); System.out.println("2个包装类的比较:" + (new Integer(2) == new Integer(2)));
7)包装类比较的特殊情况
自动装箱的结果
package cn.it.lsl; public class Primitive2Wrapper { public static void main(String[] args) { Integer a = 2; Integer b = 2; System.out.println(a == b); //输出true Integer a1 = 128; Integer b1 = 128; System.out.println(a1 == b1); //输出false } }
分析:以上程序,当两个2自动装箱后,比较相等,但是两个128自动装箱后就不相等。
这是因为系统内部提供了一个缓存功能,把-128~127之间的整数自动装箱成一个Integer时,实际上直接指向对象的数值元素,而-128~127范围外的整数自动装箱成Integer时,总是新创建一个Integer实例。
2.toString()方法
toString()是Object类里面的一个实例方法,因为所有的类都是Object的子类,所以所有的Java对象都具有toString()方法。
当打印一个对象的时候,总是会调用toString()方法。在缺省状态下,其输出时类名、符号名@、对象的hashCode()值。
package cn.it.lsl; public class ToStringWithout { int x; int y; public ToStringWithout(int x,int y){ this.x = x; this.y = y; } public static void main(String[] args) { System.out.println(new ToStringWithout(23,33)); } }
输出:cn.it.lsl.ToStringWithout@bb0d0d
package cn.it.lsl; //覆盖toString()方法 public class ToStringWith { int x; int y; public ToStringWith(int x, int y){ this.x = x; this.y = y; } public String toString(){ return "ToStringWith[" + x + "," + y + "]"; } public static void main(String[] args) { System.out.println(new ToStringWith(23,33)); } }
输出:ToStringWith[23,33]
3.单例类
有时候,不允许自由创建一个类的实例,而只允许该类创建一个对象,这就是单例类。
1)创建单例类的方法
(1)要把构造器使用private修饰,这样就能避免其他类自由创建该类的实例。
(2)提供一个public方法作为该类的访问点,用于创建对象,且该方法应该使用static修饰。(因为调用该方法时候,对象还不存在,所以调用该方法的只能是类)
(3)该类中还要有一个缓存对象,用于判断该类是否已经创建过对象了,这样才能保证只创建一个对象,该成员应该也要static修饰。
package cn.it.lsl; class Singleton{ //使用一个变量来缓存已经创建的实例 private static Singleton instance; private Singleton(){} public static Singleton getInstance(){ /* 如果instance为null,则还未创建Singleton对象 * 如果instance不为null,则表明已经创建了Singleton对象,将不再创建 * */ if(instance == null){ instance = new Singleton(); } return instance; } } public class SingletonTest { public static void main(String[] args) { Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getInstance(); System.out.println(s1 == s2); } }
4.比较(==和equals方法)
1)若使用==对两个引用类型变量进行比较,他们必须指向同一个对象时,==判断才会是true。
2)当比较两个变量时基本类型时,且都是数值类型时,两个值相等,就会返回true
例如:
int a = 65; float b = 65.0f; System.out.println(a == b); char c = 'A'; System.out.println(a == c);
3)"hello"直接量和new String("hello")的区别?
(1)常量池的概念:专门用于管理在编译期被确定并被保存在已编译的.class文件中的一些数据。
(2)当Java程序直接使用形如"hello"的字符串直接了(包括可以在编译时就计算出来的字符串值)时,JVM将会使用常量池来管理这些字符串。
(3)当使用new String("hello")时,JVM会先使用常量池来管理"hello"直接量,再调用String类的构造器来创建一个新的String对象,新创建的String对象被保存在堆内存中。也就是new String("hello")一共产生了两个对象。
package cn.it.lsl; public class EqualDemo { public static void main(String[] args) { String s1 = "你好"; String s2 = "你"; String s3 = "好"; String s4 = "你" + "好"; //s4后面的字符串值可以在编译期就确定下来 String s5 = s2 + s3; //s5后面的字符串值不能再编译期就确定下来 String s6 = new String("你好"); System.out.println(s1 == s4); System.out.println(s1 == s5); System.out.println(s1 == s6); } }
JVM常量池保证相同的字符串直接量只有一个,不会产生多个副本。
4)equals方法
(1)equals方法是Object类提供的一个实例方法,因此所有引用变量都能调用该方法,但是该方法判断该两个对象相等的标准与使用==运算符没有区别,同样是两个引用变量指向同一个对象时才会返回true。
(2)String已经重写了Object的equals()方法,String的equals()方法判断两个字符串是否相等的标准是:只要两个字符串的字符序列相同,就返回true。
(3)Object默认提供的equals()只是比较对象的地址,多数情况下,我们需要重写equals()方法。
package cn.lsl; class Person{ private String name; private String id; public Person() { super(); // TODO Auto-generated constructor stub } public Person(String name, String id) { super(); this.name = name; this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } public boolean equals(Object obj){ if(this == obj) return true; //obj不为null,并且是Person类实例的时候 if(obj != null && obj.getClass() == Person.class){ Person personObj = (Person)obj; if(this.getId().equals(personObj.getId())){ return true; } } return false; } } public class OverrideEqualsRight{ public static void main(String[] args) { Person p1 = new Person("刘小明","1213"); Person p2 = new Person("小明","1213"); Person p3 = new Person("小刘","1215"); System.out.println(p1.equals(p2)); System.out.println(p2.equals(p3)); } }