1.String类的两种实例化方式
(1)直接赋值
String str = "hello"; //比较常用
(2)传统方法
String str = new String("hello"); //String本身是一个类,既然是类,它就存在构造方法, //这就是利用它其中一种构造方法进行赋值 //该构造方法:public String(String str)2.字符串相等比较
(1)将基本类型用"=="比较:
int x=1; int y=1; System.out.println(x==y); //true(2)将字符串用"=="比较:
String str1 = "hello"; String str2 = new String("hello"); System.out.println(str1==str2); //false
字符串内容相同,而使用"=="后输出false,利用内存图来分析:
"=="本身是进行数值比较的,如果用于对象比较,那么所比较的就应该是两个对象所保存的内存地址数值比较,而并没有比 较对象的内容。
(3)如果想要比较内容,则必须采用String类提供的equals方法。
String str1 = "hello"; String str2 = new String("hello"); System.out.println(str1.equals(str2)); //true
3.字符串常量是String的匿名对象
(1)在java中,本身没有直接提供字符串常量的概念,所有使用""定义的内容本质上来讲都是String的匿名对象。
String str1 = "hello" ; //本质上就是将一个匿名的String类对象设置有名字,而且匿名对象一定保存在堆内存中 String str2 = new String("hello") ; System.out.println(str1.equals(str2)); //true System.out.println("hello".equals(str2)); //true(2)任何的字符串常量都是String的匿名对象,所以该对象永远不会为null。
String str = null; System.out.println("Hello".equals(str)); //false
4.String类两种实例化的区别
(1)直接赋值:
String str1 = "hello" ; String str2 = "hello" ; String str3 = "hello" ; System.out.println(str1 == str2); // true System.out.println(str1 == str3); // true System.out.println(str2 == str3); // true
没有开辟新的堆内存空间的原因:String类的设计使用了共享设计模式。在JVM底层实际上会自动维护一个对象池(字符串对象池),如果现在采用了直接赋值的模式进行String类的对象实例化操作,那么该实例化对象(字符串内容)将自动保存到这个对象池之中。如果下次继续使用直接赋值的模式声明String类对象,此时对象池之中如若有指定内容,将直接进行引用;如若没有,则开辟新的字符串对象而后将其保存在对象池之中已供下次使用(对象池就是一个对象数组,目的是减少开销)。
(2)采用构造方法:
String str = new String("hello");
通过分析可知,如果使用String构造方法就会开辟两块堆内存空间,并且其中一块堆内存将会成为垃圾空间。
在String类中提供有方法入池操作public String intern();
如:
String str1 = new String("hello").intern(); String str2 = "hello"; System.out.println(str1==str2); //true
我们一般会采用直接赋值的方法。
5.字符串常量不可变更
字符串一旦定义不可改变,所有的语言对于字符串的底层实现,都是字符数组,数组的最大缺陷就是长度固定。在定义字符串常量时,它的内容不可改变。
String str = "hello"; str = str+"world"; str += "!!!"; System.out.println(str); //hello world!!!
以上字符串的变更是字符串对象的变更而非字符串常量。
可以发现字符串上没有发生任何变化,但是字符串对象的引用一直在改变,而且会形成大量的垃圾空间。
6.与字符串有关的一些常见方法
7.StringBuffer类
由于String的不可更改特性,为了方便字符串的修改,提供StringBuffer类。在String中使用"+"来进行字符串连接,但是这个操作在StringBuffer类中需要更改为append()方法:
public synchronized StringBuffer append(各种数据类型 b)
如:
StringBuffer a = new StringBuffer(); a.append("hello").append(" world"); System.out.println(a); //输出:hello worldString和StringBuffer最大的区别在于:String的内容无法修改,而StringBuffer的内容可以修改。频繁修改字符串的情况考虑使用StringBuffer。
注意:String和StringBuffer类不能直接转换。如果想要互相转换,可以采用如下原则:
·String变为StringBuffer:利用StringBuffer的构造方法或append()方法
·StringBuffer变为String:调用toString()方法
除了append()方法外,StringBuffer也有一些String类没有的方法:
(1)字符串反转:
public synchronized StringBuffer reverse()
如:
StringBuffer a = new StringBuffer("hello world"); System.out.println(a.reverse()); //输出:dlrow olleh
(2)删除指定范围的数据:
public synchronized StringBuffer delete(int start,int end) //区间是左闭右开[)
如:
StringBuffer a = new StringBuffer("hello world"); System.out.println(a.delete(5, 10)); //输出:hellod
(3)插入数据:
public synchronized StringBuffer insert(int offset,各种数据类型 b)
如:
StringBuffer a = new StringBuffer("hello world"); System.out.println(a.insert(0,123)); //输出:123hello world二、Object类
1.简介:Object是Java默认提供的一个类。Java里面除了Object类,所有的类都是存在继承关系的。默认会继承Object父类。即所有类的对象都可以使用Object进行接收。
如:
class Person{} class Student{} public class Test{ public static void main(String[] args) { fun(new Person()); fun(new Student()); } public static void fun(Object obj){ System.out.println(obj); } } //输出:Person@6d06d69c // Student@7852e922
Object类存在的定义好的一些方法:
2.取得对象信息
在使用对象直接输出的时候,默认输出的是一个地址编码。如果现在使用的是String类,该类对象直接输出的是内容,主要原因就是toString()方法的问题。如若觉得默认给出的toString()方法功能不足,就在需要的子类上覆写toString()方法。
如:
class Person{ private String name; private int age; public Person(String name,int age){ this.age = age; this.name = name; } public String toString(){ //覆写toString() return "姓名:"+this.name+" 年龄:"+this.age; } } public class Test{ public static void main(String[] args) { fun(new Person("张三"),10); //姓名:张三 年龄:10 fun("hello"); //hello } public static void fun(Object obj){ System.out.println(obj.toString()); } }String作为信息输出的重要数据类型,在Java中所有的数据类型只要遇见了String并且执行了"+",那么都要求将其变为字符串后连接,而所有对象要想变为字符串就默认使用toString()方法。
3.对象比较
String类对象的比较使用的是equals()方法,实际上String类的equals()方法就是覆写的Object类中的equals()方法。
class Person{ private String name; private int age; public Person(String name,int age){ this.name = name; this.age = age; } public String toString(){ //覆写toString() return "姓名:"+this.name+" 年龄:"+this.age; } public boolean equals(Object obj){ //覆写equals() if(obj == null){ return false; } if(this == obj){ return true; } if(!(obj instanceof Person)){ return false; } Person person = (Person) obj; return this.name.equals(person.name) && this.age == person.age; } } public class Test{ public static void main(String[] args) { Person per1 = new Person("张三", 10); Person per2 = new Person("张三", 10); System.out.println(per1.equals(per2)); } }4.接收引用数据类型
Object可以接收任意的对象,因为Object是所有类的父类,但是Object并不局限于此,它可以接收所有数据类型,包括:类、数组、接口。
(1)使用Object来接收数组对象
Object obj = new int[]{1,2,3,4,5}; //Object接收数组对象,向上转型 int[] data = (int[]) obj; //向下转型,需要强转
(2)使用Object接收接口对象(Object可以接收接口是Java中的强制要求,因为接口本身不能继承任何类)
interface IMessage{ public void getMessage(); } class MessageImpl implements IMessage{ public String toString(){ return "hello"; } public void getMessage(){ System.out.println("你好"); } } public class Test{ public static void main(String[] args) { IMessage msg = new MessageImpl(); //子类向父类接口转型 Object obj = msg; //接口向Object转型 System.out.println(obj); //hello IMessage temp = (IMessage) obj; //强制类型转换 temp.getMessage(); //你好 } }三、包装类
1.原理:包装类就是将基本数据类型封装到类中。
如:自己定义一个包装类
class IntDemo{ private int num; public IntDemo(int num){ this.num = num; } public int intValue(){ return this.num; } } //IntDemo实际上就是int数据类型的包装类,利用intValue就可以实现基本数据类型变为对象的需求。 public class Test{ public static void main(String[] args) { Object obj = new IntDemo(10); //子类对象向上转型 IntDemo temp = (IntDemo) obj; //向下转型 System.out.println(temp.intValue()); //取出里面的基本数据类型 } }2.Java为了方便开发,专门提供了包装类的使用,而对于包装类的使用,提供了两种类型。
·对象型(Object的直接子类):Boolean、Character(char);
·数值型(Number的直接子类):Byte、Double、Short、Long、Integer(int)、Float;
3.装箱与拆箱
·装箱:将基本数据类型变为包装类对象,利用每一个包装类提供的构造方法实现装箱处理。
·拆箱:将包装类中包装的基本数据类型取出。
如:手工装箱和拆箱
Integer num = new Integer(10); //装箱 int data = num.intValue(); //拆箱
如:自动装箱与拆箱
Integer x = 10; //自定装箱 System.out.println(x*2); //可以直接利用包装类对象操作在这里面依旧存在"=="和"equals"问题;
如:
Integer num1 = new Integer(10); Integer num2 = new Integer(10); System.out.println(num1 == num2); //false System.out.println(num1 == new Integer(10)); //false System.out.println(num1.equals(new Integer(10))); //true说明:对Integer var的赋值在-128~127之间时,Integer对象是在IntegerCache.cache产生,会复用已有对象,这个区间内的Interger可以直接使用==判断,但是在这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,可以用equals判断。
4.字符串与基本数据类型转换
(1)将字符串变为int型
String str = "123"; int num = Integer.parseInt(str);
(2)将字符串变为double
String str = "123"; double num = Double.parseDouble(str);注意:将字符串转为数字的时候,字符串的组成有非数字,那么转换就会出现错误。而字符串与boolean转换就不受此影响。
如果要将基本数据类型转变为字符串:
·任何数据类型使用了"+"连接空白字符串就变为了字符串类型。
·使用String类中提供的valueOf()方法,此方法不产生垃圾。