当前位置 博文首页 > 不负时光可怜人:【伍】一篇让你搞懂Java中的字符串,两种实例化
字符串广泛应用 在 Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串
String并不是一个基本数据类型,它本身属于一个类,但是这个类在设计的过程之中加入了一些Java自己的特殊支持所以对于这个类的对象实例化方式就有两种形式:
直接赋值:String 对象=“内容”
构造方法;public String(String s)
//直接赋值法
String str1="Hello";
//构造方法
String str2=new String("World");
如果说现在有两个int
型的变量,那么要进行相等的判断,则直接使用“==”即可。但如果现在将同样的操作形式用在String上呢?
String stra="hello";
String strb=new String("hello");
String strc=strb; //引用传递
System.out.println(stra==strb); //false
System.out.println(strb==strc); //true
System.out.println(stra==strc); //false
所以发现在程序中如果使用“==”比较的只是两个对象(任意的引用类型)堆内存数值,属于数值内容的比较并不是堆内存中保存内容的比较,那么要想进行String对象内容的比较则可以利用String类中提供的一个方发完成:
字符串比较:public boolean equals(String str)
String stra="hello";
String strb=new String("hello");
String strc=strb; //引用传递
System.out.println(stra.equals(strb)); //true
System.out.println(strb.equals(strc)); //true
System.out.println(strc.equals(strc)); //true
==:是直接比较的两个对象的堆内存地址,如果相等,则说明这两个引用实际是指向同一个对象地址的.
更多内容请参考链接:在java中==和equals()的区别
字符串的描述在很多语言之中都使用字符数组表示。在Java的设计之初为了解决这样的问题,专门提供了一个String类来进行描述。但是随着发展,为了能够让程序变得更加的,易于开发,所以在Java里面也提供双引号声明的数据,而这些数据,在Java中并不是普通的变量,而是属于String类的匿名对象。
String str="hello";
System.out.println("hello".equals(str)); //true
现在发现,此时已经可以通过字符串调用equals()方法,那么就证明一点,字符串的确是String类的匿名对象。那么之前的String字符串对象=“字符串”;本质就是为一个字符串的匿名对象起了一个名字。
开辟一块堆内存空间,并且一个栈内存将直接指向该堆内存空间
String str="hello"; //假设为输入数据
System.out.println(str);
String stra="hello";
String strb="hello";
String strc="nihao";
System.out.println(stra==strb); //true
System.out.println(stra==strc); //false
System.out.println(strb==strc); //false
在Java设计的过程之中为了方便用户的代码编写开发,针对于几个特殊的类使用了共享设计思路,其中String就属于这其中一员。这种设计思路是java自己的支持,而且只针对于直接赋值的情况。
在使用直接赋值实例化String类对象的操作之中,字符串的内容定义之后实际上会自动将其保存在一个对象池之中,后如果现在有其他的字符串对象也采用了直接赋值的形式,并且内容与之前的字符串内容完全相同,那么不会开辟新的堆内存空间,而是通过对象池知道自己有的堆内存空间地址,直接引用即可,所以就会造成若干个字符串直接赋值之后,当内容相同时,地址是完全相同的,所“==”的结果也是相同的,这样的设计就是共享设计模式。
通过此时的内存分析可以发现,如果采用了构造方法进行String类对象的实例化操作,那么最终将产生两块堆内存,其中有一块是垃圾空间。
String str=new String("hello");
System.out.println(str);
我们刚才有了解过对象池的概念,但是如果使用了构造方法来进行String类对象实例化,那么所产生的的对象不会保存在对象池之中,也就是说此对象无法重用。
如果用户需要让这个对象入池,只能通过手工的方式来实现:
public String Intern()
String stra=new String("hello").intern(); //构造方法
String strb="hello"; //直接赋值
System.out.println(stra==strb); //true
intern()
自动入池参考链接:Java中String类两种实例化的区别
字符串一旦声明则不可改变,通过“+”可实现字符串改变,下面请看代码和内存分析加深理解。
String str="Hello";
str+="World";
str=str+"!!!";
System.out.println(str); //HelloWorld!!!
可以发现整个的操作流程之中,都是String类对象的引用发生着改变,而字符串的内容没有改变,因此,这样的操作会产生垃圾,所以在实际开发中,不要进行频繁的修改操作。
方法名称 | 类型 | 描述 | |
---|---|---|---|
1 | public String(char[] value) | 构造 | 将全部的字符数组作为String的内容 |
2 | public String(char[] value,int offset,int count) | 构造 | 将部分的字符数组变为字符串,设置字符数组的开始索引与使用个数 |
3 | public char charAt(int index) | 普通 | 返回指定索引位置上的字符 |
4 | public char[] toCharArray() | 普通 | 将字符串以字符数组的形式返回 |
String str="hello";
char c=str.charAt(0);
System.out.println(c); //h
//在程序中字符串索引是从0开始的
String str="helloworld";
char[] data=str.toCharArray(); //将字符串变为字符数组
for(int x=0;x<data.length;x++){
System.out.print(data[x]+" ");
} //h e l l o w o r l d
//当字符串变为字符数组之后就可以针对于里面的每一个字符进行操作。
String str="helloworld";
char[] data=str.toCharArray(); //将字符串变为字符数组
for(int x=0;x<data.length;x++){
data[x]-=32; //编码减去32,成大写
}
System.out.println(new String(data));
System.out.println(new String(data,5,5)); //第5个索引,之后取5个长度的内容
现在至少应该知道了字符串比较有一个equals()方法,但是此方法本身是属于区分大小写的比较,为此在Java里面针对于字符串的比较实际上还有其他方法。
方法名称 | 类型 | 描述 | |
---|---|---|---|
1 | public boolean equals(Object anObject) | 构造 | 区分大小写的字符串比较 |
2 | Public boolean equalsIgnoreCase(String anotherString) | 普通 | 不分区大小写的字符串比较 |
3 | public int compareTo(String anotherString) | 普通 | 比较字符串大小 |
4 | public int compareToIgnoreCase(String str) | 普通 | 不区分大小写比较字符串大小 |
String strA="hello";
String strB="HEllo";
System.out.println(strA.equals(strB)); //false
System.out.println(strA.equalsIgnoreCase(strB)); //true
在进行字符串相等的比较操作之中,最为关键的一个方法是:compareTo(),这个方法本身返回一个int型数据,而这个int型数据有三种结果:大于(>0)、小于(<0)、等于(=0)
String strA="A";
String strB="a";
System.out.println(strA.compareTo(strB)); //-32
System.out.println(strA.compareToIgnoreCase(strB)); //0
方法名称 | 类型 | 描述 | |
---|---|---|---|
1 | public boolean contains(CharSequence s) | 普通 | 判断某一个字符串是否存在 |
2 | public int indexOf(String str) | 普通 | 取得某一个字符串的索引位置,找不到返回-1 |
3 | indexOf(String str, int fromIndex) | 普通 | 从指定索引位置开始检索子字符串位置,找不到就返回-1 |
4 | public int lastIndexOf(String str) | 普通 | 从后向前查找指定字符串的位置,找不到返回-1 |
5 | public int lastIndexOf(String str,int fromIndex) | 普通 | 从指定位置由后向前查找子字符串的位置,找不到返回-1 |
6 | public boolean startsWith(String prefix) | 普通 | 判断是否以某个字符串开头 |
7 | public boolean startsWith(String prefix,int toffset) | 普通 | 从指定位置判断是否以某个字符串开头 |
8 | public boolean endsWith(String suffix) | 普通 | 是否以指定的字符串结尾 |
contains()
方法如果要查找中间的内容,那么现在基本上都使用contains()方法
String str="hello"; //0:h、1:e、2:l、3:l、4:o。
if(str.contains("l")){ //找到此方法直接返回true或者是false
System.out.println("已查找到!");
}
indexOf()
方法判断 String str="hello"; //0:h、1:e、2:l、3:l、4:o。
System.out.println(str.indexOf("l")); //2,第一个满足的位置
if(str.indexOf("l")!=-1){ //现在表示索引查找到了
System.out.println("内容已经查到到!");
}
String str="**@@hello##";
System.out.println(str.startsWith("*")); //true
System.out.println(str.startsWith("@@",2)); //true
System.out.println(str.endsWith("##")); //true
方法名称 | 类型 | 描述 | |
---|---|---|---|
1 | public String substring(int beginIndex) | 普通 | 从指定索引位置截取到结尾 |
2 | public String substring(int beginIndex,int endIndex) | 普通 | 截取指定索引范围的内容 |
String str="helloworldmldn";
System.out.println(str.substring(5)