Java基础 四
关键词: 包装类,Object类 ,String类,==与equals的区别,StringBuffer类,StringBuilder类
1. java 8个基本类型的包装类
大家都知道Java有8个基本类型(boolean、byte、short、int、long、float、double、char),Java是面向对象的编程语言,但这8个基本数据类型是不支持面向对象的编程机制的,即基本类型没属性、方法可以被调用。
有时某个方法需要object类型的参数,但实际需要的值却是2、3等数值,基本数据类型就不能满足这种条件了。Java为了解决8个基本数据类型的变量不能当成object类型变量使用的问题,Java为这8个基本类型提供了对应的包装类,通过这些包装类可以把8个基本类型的值包装成对象使用。
8个基本数据类型和包装类之间的对应
基本数据类型 包装类
byte Byte
short Short
int Integer [ˈɪntɪdʒɚ]
long Long
char Character
float Float
double Double
boolean Boolean
8个基本类型对应的包装类都是首字母大写。
基本类型与对应的包装类之间的转换
例: int-->Integer
/*
int i = 1;
// Integer in = new Integer(i); //通过Integer构造器将基本类型转换成包装类对象
// Integer in = i; //从JDK1.5开始,JDK提供了自动装箱和自动拆箱共能,自动装箱:基本类型变量直接赋值给对应的包装类变量。自动拆箱:包装类对象直接赋值给对应的基本类型变量。
// Integer in = Integer.valueOf(i); //通过Integer提供的静态方法将基本类型变量转换成对应的包装类变量。
*/
例:Integer-->int
/*
Integer in = new Integer(1);
// int i = Integer; //自动拆箱功能。
// int i = Integer.intValue();
*/
例:String-->Integer
/*
Srting s = "123";
// Integer in = Integer.parseInt(s);
// Integer in = new Integer(s);
*/
例:Integer-->String
/*
Integer in = new Integer(123);
int i = 123;
// String s = in.toString();
// String s = in+"";
// String s = i + "";
*/
2. Object类
Object类是所有类、数组、枚举类的父类,也就是说,Java允许把任何类型的对象包括八大基本类型的任何一种赋值给Object类型的变量。当定义一个类时没有使用extends关键词时,则该类默认继承Object父类。
Object类提供的方法:
boolean equals(object obj)
判断指定对象与该对象是否相等。判断标准:两个对象应用变量是否指向同一地址。
protected void finalize()
当系统中没有引用变量引用到该变量时,垃圾回收器调用此方法来清理该对象的资源。
String toString()
返回该对象的符号表示 ,当我们使用System.out.println方法输出一个对象或某个对象和字符串连接时,系统会自动调用toString方法返回该对象的字符串表示。Object的toString方法返回”运行时类名@16进制hashCode值“(hashCode是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值)格式的字符串,但很多类都重写了Object类的toString方法,用来描述对象的所有状态信息。
除此之外Object还提供了其他的几个方法。
3. String类
是不可变类!即一旦一个String对象被创建以后,包含在这个对象中的字符序列是不可改变的(不能对原有的数据进行插入,删除部分,但是可以在末尾添加),直至这个对象被销毁。
toString方法——重写了Object类的toString方法,使之显示String对象中的内容。
例:toString方法的重写
/*
class People{
private String name;
public People(String name,int age){
this.name = name;
this.age = age;
}
public String toString(){
return "姓名:"+name+",年龄:"+age;
}
}
public class Test{
public static void main(String [] args){
People p = new People("李华",18);
System.out.println(p); //当输出p对象时,实际上p对象会调用toString方法,输出的是toString的返回值。注意!只有当输出时才会自动调用toString方法。
System.out.println(p.toString());
People p2 = p;
System.out.println(p == p2);//输出true,不会调用toString方法。
}
}
*/
输出结果:
姓名:李华,年龄:18
姓名:李华,年龄:18
例:字符串常量的理解
String s = ”I”+“Love”+“Java”;
上面的程序除了使用了3个字符串常量(临时变量)之外,还会额外生成2个字符串常量(临时变量),其中”I“和”LOVE”生成了“ILOVE”保存在内存中,接着“ILOVE”与“Java”生成了“ILOVEJava”字符串并将它赋给s变量。因为String是不可变的所以会额外产生很多临时变量,这些临时变量都存储在
JVM中的常量池中。
常量池:是指在编译期被确定,并被保存在以编译的.class文件中的一些数据。它包括关于类、方法、接口中的常量,同时也包括了字符串常量。
4. ==与equals的区别
Java程序中测试两个变量是否相等有两种方式,一种是利用==运算符,另一种是利用equals方法。
==判断两个变量是否相等
如果两个变量是基本类型的变量,且都是数值型,则只要两个变量的值相等,使用==判断将会返回true。
如果两个变量是引用变量,必须他们指向同一个对象时(也就是判断内存地址是否一致),==判断才会返回true。
例:
/*
int i = 1;
int j = 1;
System.out.println(i==j); //将输出true
float f = 1.0f;
System.out.println(i==f); //将输出true
i = 65;
char ch = 'A';
System.out.println(i==ch); //将输出true
String s1 = new String("haha");
String s2 = new String("haha");
System.out.println(s1==s2); //将输出false
String s3 = s1;
System.out.println(s1==s3); //将输出true
*/
例:
【转】String 的经典笔试题一
String s = new String("abc");
String s1 = "abc";
String s2 = new String("abc");
System.out.println(s == s1);
System.out.println(s == s2);
System.out.println(s1 == s2);
请问 前面三条语句分别创建了几个对象,分别是什么.后面的输出分别是什么?
答:
(1)String s = new String("abc"); 这句,创建了两个对象,其内容都是"abc".注意,s不是对象,只是引用变量.只有new生成的才是对象.
创建的流程是,首先括号里 的"abc"先到常量池里看有没"abc"这个对象,没有则创建这个对象。所以这里就在常量池中创建了一个"abc"对象。然后 通过new语句又创建了一个"abc"对象,而这个对象是放在内存的堆里,这里的s指向堆里的对象.
(2) String s1 = "abc"; 这条语句,s1当然还是引用。后面的"abc",其实就是上面括号里的"abc".执行的是相同的操作.即 在常量池里查找有没"abc"这个对象.没有则创建一个,很显然,第一条语句已经创建了一个"abc".所以这条语句没有创建对 象,s1指向的是常量池中的"abc"
(3)String s2 = new String("abc"); 这条语句,其实和第一条是一样的,但是,因为第一条已经在常量池中创建了"abc"这个对象,所以,这条语句创建了一个对象.s2指向的是堆里 的"abc"。注意,虽然内容都是"abc",s与s2表示的是不同的对象
(4)下面的三个==判断.(注意,==永远是判断内存地址是否相等) s与s1,一个指向堆里的对象,一个指向常量池里的.很明显是不同的对象.s与s2.上面说了,虽然都是指向堆里的对象,内容也是"abc",但是也不 是相同的对象.s1与s2.一个指向常量池,一个指向堆.也不是相同的对象.所以三个都返回false.
例:
【转】String 的经典笔试题二
String s = new String("abc");
String s1 = "abc";
String s2 = new String("abc");
System.out.println(s == s1.intern());
System.out.println(s == s2.intern());
System.out.println(s1 == s2.intern());
System.out.println(s1 == s2);
求最后输出是什么?
答:
最后的答案是 false false true false。
intern()方法就是扩充常量池的一个方法;当一个String实例s调用intern()方法时,Java查找常量池中是否有相同的字符串常量,如果有,则返回这个字符串常量的引用但不会更改s的引用,如果没有,则在常量池中增加一个等于s的字符串常量并返回它的引用但不会更改s的引用;
这样就很容易理解了。s1.intern返回的是常量池里的"abc"对象.与s这个堆里的对象肯定不同,返回false.同理,s与s2.intern()也肯定不 同,返回false.第三个,s1与s2.intern().其中s2.intern()返回的是常量池中的"abc"对象,而s1也是指向常量池中 的"abc"对象.所以返回的是true:对于最后的一个语句,虽然上一条语句s2调用了intern方法,但是并没有改变s2的引用s2仍指向堆里的对象,s1指向的是常量池的对象,故返回的是false
例:
【转】String 的经典笔试题三
String hello = "hello";
String hel = "hel";
String lo = "lo";
System.out.println(hello == "hel" + "lo");
System.out.println(hello == "hel" + lo);
System.out.println(hello == hel + lo);
求输出的结果
答:
最后答案是 true false false
首先,上面已经说明了,hello hel lo这三个都是指向常量池中的对象。
现在我们考虑"hel" + "lo" 按照内容来说,两个相加也就是"hello".这个时候,这个会返回常量池中的"hello"对象.所以,hello == "hel" + "lo" 返回的是true .
而"hel" + lo 虽然内容也是"hello",但是它将在堆里面生成一个"hello"对象,并返回这个对象。所以这里的结果是false。
同理hel + lo 虽然内容也是"hello",但是它也会在堆里面生成一个"hello"对象,并返回这个对象。所以这里的结果是false
equals
equals 方法也是Object类提供的一个实例方法,所有Java对象都可调用equals方法。
Object类判断两个对象是否相等的标准与==相同,只有两个变量指向同一个对象时才会返回true。
例:
/*
class A{
}
public class B{
public static void main(String[] args){
A a1 = new A();
A a2 = new A();
A a3 = a2;
System.out.println(a1.equals(a2)); //将输出false
System.out.println(a1.equals(a3)); //将输出false
System.out.println(a3.equals(a2)); //将输出true
String s1 = new String("asd");
String s2 = new String("asd");
String s3 = "asd";
System.out.println(s1.equals(s2)); //将输出true
System.out.println(s1.equals(s3)); //将输出true
System.out.println(s3.equals(s2)); //将输出true
}
}
*/
上例中String变量中s1,s2都是通过new创建过的实例,两个变量引用的地址是不一样的,那为什么会相等呢?
这是因为String重写了equals对象,提供了判断两个变量相等的标准。(判断两个字符串相等的标准是:只要两个字符串所包含的字符序列相同,则通过equals比较将返回true)。
所以当我想通过equals判断我们自定义的对象是否是相同的,那我们得重写equals方法,给出我们的判断标准。
4. StringBuffer类
StringBuffer是一个可变的字符串,当一个StringBuffer被创建后,通过StringBuffer提供的append(末尾添加)、insert(插入)、reverse(翻转)、setCharAt(设置指定位置的字符)、setLength(设置字符串长度)等方法可以改变这个这个字符串对象。
注意:当setLength的长度小于字符串的长度时,会截取掉末尾多余的不封。
如:
String s = “hellojava”
s.setLength(5); //s会变为“hello”
5. StringBuilder类
和StringBuffer基本类似。不同的是,StringBuffer是线程安全的,而StringBuilder则没有实现线程安全功能,但性能略高。
尊重原创,写博不易,转载请注