包装类
Java是面向对象的编程语言,有8中基本的数据类型,但是这8中数据类型不具备面向对象的编程机制,基本数据类型对象也不具备“对象”特性:没有成员变量、方法可以被调用。
所有引用类型的变量都是继承了Object类,都可当成Object类型变量使用,但是基本的数据类型不行。所以Java提供了包装类,为这8种基本数据类型提供相应的引用类型,并称之为基本数据类型的包装类。int包装类是Integer,char包装类是Character,其他的就是基本数据类型首字母大写。
除了Character之外,可以通过传入一个字符串参数来构建包装类对象。
自动装箱:把一个基本类型变量直接赋给对应的包装类变量,或者赋给Object变量(Object是所有类的父类,子类对象可以直接赋给父类变量);
自动拆箱:与自动装箱相反,允许直接把包装类对象直接赋给一个对应的基本类型变量。
public class BoxTest{ public static void main(String[] args){ //自动装箱,把基本数据类型赋给包装类对象 Integer i = 5; System.out.println(i); } }
进行自动装箱和自动拆箱时必须注意类型匹配。注:即使赋给Object类型变量,也是利用Java向上自动转型特性,不要多想。
包装类还可以实现基本类型变量和字符串之间的转换。
把字符串类型转换为基本数据类型的值有两种方法:
1、利用包装类提供parseXxx(String s)静态方法(除了Character以外的所有包装类都提供了该方法)
public class ParseTest{ public static void main(String[] args){ String istr = "123"; //使用包装类提供的parsexXX()方法把字符串转换为基本数据类型 int in = Integer.parseInt(istr); System.out.println(in); //Character没有提供parseXxx()方法,所以下面程序出错 //char c = Character.parseChar(istr); } }
2、利用包装类提供的Xxx(String s)构造器,传入一个字符串参数来构建包装类对象
public class ParseTest{ public static void main(String[] args){ String istr = "123"; Integer in = new Integer(istr); System.out.println(in); } }
String提供了多个重载valurOf()方法,用于将基本类型变量转换成字符串
public class ValueOfTest{ public static void main(String[] args){ int a = 123; String s = String.valueOf(a); System.out.println(s); } }
还有一种更简单的方法,把基本类型变量和""进行连接运算,系统会自动把基本数据类型转换为字符串
int a = 123; //基本数据类型和双引号""连接运算 String s = a + " ";
包装类型的变量是引用类型,但包装类实例可以与数值类型的值进行比较,这种比较是直接取出包装类实例所包装的数值进行比较
Integer i = new Integer(6); //包装类实例直接与基本数据类型比较 System.out.println(a > 5);
两个包装类实例比较的情况比较复杂,包装类的实例实际上是引用类型,只有两者指向同一对象才会返回true,即两者指向同一内存返回true。
//返回false System.out.println(new Integer(2) == new Integer(2));
自动装箱就是可以把一个基本类型值赋给一个包装类实例
对象的处理
Java对象都是Object类的实例,都可以直接调用该类中定义的方法,这些方法是处理Java对象的通用方法。
class Person{ private String name; public Person(String name){ this.name = name; } } public class PersonTest{ public static void main(String[] args){ Person p = new Person("影流之主"); System.out.println(p); } }
上面程序输出
[email protected]
如果改为
System.out.println(p.toString());
结果还是一样。toString()是一个非常特殊的方法,它是一个“自我描述”方法,该方法功能:当程序员需要打印该对象时,系统将会输出该对象的“自我描述”信息,用以告诉外界该对象具有的状态信息。
Object类提供的toString()方法总是返回该对象实现类的“类名 + @ + hashCode”值,这并不能真正实现自我描述功能,所以用户需要自动以类能显示“自我描述”的功能。
class Person{ private String name; public Person(String name){ this.name = name; } //重写toString()方法 public String toString(){ return name; } } public class PersonTest{ public static void main(String[] args){ Person p = new Person("影流之主"); System.out.println(p); } }
== 和 equals()方法
Java测量两个变量是否相等有两种方法:一种是 == 运算符,一种是equals()方法。
当使用==判断的时候,如果两个是基本数据类型变量,且都是数值类型,只要两个变量的值相等,返回true。
但引用类型变量只有指向统一对象才会返回true。
public class EqualsTest1{ public static void main(String[] args){ String str1 = new String("hello"); String str2 = new String("hello"); //使用==判断引用类型是否相等,返回false System.out.println(str1 == str2); } }
常量池:专门用于管理在编译时被确定并被保存在已编译.class文件中的一些数据。它包括关于类、方法、接口中的常量,还包括字符串常量。
public class ChangLiangChiTest{ public static void main(String[] args){ //s1直接引用常量池中的 疯狂Java讲义 String s1 = "疯狂Java讲义"; String s2 = "疯狂"; String s3 = "Java讲义"; //s4的字符串在编译时就确定下来,直接引用常量池中的 String s4 = "疯狂" + "Java讲义"; //s5字符串不能在编译时就确定下来,不能引用常量池中的 String s5 = s2 + s3; //使用new创建一个新的String对象,s6引用堆内存中的String对象 String s6 = new String("疯狂Java讲义"); } }
JVM常量池可以保证相同的字符串直接量只有一个,不会产生副本,s1和s2使用同一字符串对象。
new String()创建的字符串对象运行时创建出来,被保存在运行时堆内存,不会放到常量池。
对于两个字符串变量,只是要求它们引用字符串对象的字符序列相同即可认为相等。此时利用String对象的equals()方法进行判断就可以。
equals()方法是Object类提供的一个实例方法,所有引用变量都可以调用该方法判断是否与其他引用变量相等。但使用这个方法判断两个对象是否相等与使用==运算符没有区别,同样要求两个引用变量指向同一对象返回true。这样的话就没有太大的意义了,如果希望自动了相等标准,可以重写equals方法。
String已经重写的equals方法,String的equals方法判断两个字符串相等的标准是:只要两个字符串所包含的字符序列相同,equals返回true。
class Person{ //省略…… //重写equals()方法,提供自定义相等标准 public boolean equals(Object obj){ //如果两个对象为同一对象 if(this == obj){ return true; } //只有当obj是Person对象 if(obj != null && obj.getClass() == person.class){ Person personObj = (Person)obj; //并且当前对象的idStr和obj的idStr相等,才可判断两个对象相等 if(this.getIdStr().equals(PersonObj.getIdStr())){ return true; } } return false; } }
类成员
static修饰的成员是类成员,属于整个类。
Java类里只能包含变量、方法、构造器、初始化块、内部类(包括接口、枚举)
类变量属于整个类,系统第一次准备使用该类时,就会为该类变量分配内存。知道该类被卸载,变量所占内存才会被系统回收机制回收。
当通过对象来访问类变量时,系统会在底层转换为通过该类来访问类变量。
当使用实例来访问类成员时,实际上是委托该类来访问类成员,因此即使某个实例为null,它也可以访问它所属的类成员。