1.java.lang.String类
String类是一个引用数据类型,是被final修饰的类,不能被继承
String也有构造方法。
1.String类的两种赋值方式
1.1直接赋值:
直接赋值的数据在堆上开辟空间
java为String类提供了缓冲池机制的功能,当直接给字符串赋值时,JVM会先到缓冲池寻找是否存在内容相同的字符串,若有就直接使用,不另辟空间,若没有,就在缓冲池内创建一个新的空间保存字符串供下次使用。
String str="hello";
1.2通过构造方法实例化对象(直接方法)
用构造方法为实例化对象赋值时,jvm会开辟开辟两片内存空间,因为一个字符串就是一个匿名对象,会在堆内存开辟一片空间,当用了new以后,会再开辟一个堆空间,供栈内存引用,因此第一次开辟的堆内存空间就成了来及空间,会被GC回收,增大了开销。
String str1=new String("hello");
手工入池操作:public native String intern();
是一个本地方法,函数体在系统底层开发语言C语言中,是一个成员方法,需要对象调用。intern()方法的返回值是一个字符串。
String str2=new String("hello").intern();//new开辟的堆内存空间入池
入池操作可减少开销,提高性能,入池后用“==”比较两个相同的字符串,返回结果为true,因为是同一片内存地址,没有新开辟空间。
String str1="nihao";//直接赋值,自动入池,一片堆空间
String str2="nihao";//池中存在,不开辟堆空间
String str3="nihao";//池中存在,不开辟堆空间
String str4=new String("nihao");//构造方法赋值,开辟两块堆空间
以上代码段一共在堆内存上开辟了3片堆内存空间
2.字符串相等比较
“==”比较运算符只能比较数值是否相等,对于字符串不能用“==”比较,因为String是引用数据类型,若用“==”比较,比较的是字符串的地址,因此要比较字符串的内容只能用方法equals()public boolean equals(String anotherString)
比较,equals方法只是一个成员方法,因此要用对象调用。
str.equals(anotherString)
使用equals 方法时,若要判定用户输入的字符串是否与特定字符串相等,那么尽量将特定字符串写在前面,避免了用户输入为空时会造成空指针异常。
3.字符串常量(“”括起来的内容)是String的匿名对象
验证方法:"hello".equals(str1);
返回结果为true.
4.字符串常量不可变更
字符串常量一旦定义后不可修改,若进行了修改,会另外开辟新的堆空间(字符串对象)。
String str="hello";//产生符串对象"hello"
str=str+"world";//产生字符串对象 "world","hello world"
str+="!!!";//产生字符串对象 "!!!","hello world !!!"
System.out.println(str);//此段代码共产生了5个字符串对象。
5.字符与字符串的相互转换
a.将字符数组转为字符串
public String(char[] value);//构造方法,使用构造方法赋值时使用
public String(char[] value,int offset,int count)//构造方法,使用构造方法赋值时使用
b.将字符串转为单个字符
public char charAt(int index);//返回值为字符,参数为字符串索引
c.将字符串变为字符数组
public char[] toCharArray();
char[] data=new char[]{'h','e','l','l','o'};//定义字符数组
String str=new String(data);//通过字符串的构造方法将字符数组转为字符串
System.out.println(str);
char c="hello".charAt(1);//将字符串转为字符,取索引为1的字符
System.out.println(c);
char[] chars="hello".toCharArray();//将字符串串转为字符数组
System.out.println(chars);
System.out.println(chars.length);//数组有length属性
System.out.println("nihao".length());//字符串有length方法
字节与字符串
1.将字符串转为字符数组
public String(byte[] value)
public String(byte[] value,int offset,int length)
public void code4(){
byte[] by=new byte[]{1,2,3};
String str=new String(by);
System.out.println(str);
}
2.将字符串转为字节数组
字节不适合处理中文,字节只适合处理二进制字节
public byte[] getBytes();
public void code5(){
String str="hello";
byte[] by=str.getBytes();
for(int i=0;i<by.length;i++){
System.out.println(by[i]);
}
3.将字符串按照指定编码转为字节数组
public byte[] getBytes(String charsetName);
字符串比较
1.不区分大小写相等比较
public boolean equalsIgnoreCase(String str)
public void code6(){
String str1="hello";
String str2="Hello";
System.out.println(str1.equalsIgnoreCase(str2));
}
2.比较两个字符串的大小
public int CompareTo(String str)//返回值0:表示等于比较对象
//返回值大于0:表示大于比较对象
//返回值小于0:表示小于比较对象
字符串查找
1.判断本字符串是否存在
public boolean contains(String s)
String str1="hello";
String str2="Hello";
System.out.println(str1.contains(str2));//false
2.判断是否以指定字符串开始
String str1="hello";
String str2="Hello";
System.out.println(str1.startsWith(str2));
3.是否以指定字符串结尾
System.out.println("skfdk".endsWith("k"));
4.使用indexof()进行位置查找
一旦查找到立即返回索引,未查找到返回-1
String str="helloworld";
System.out.println(str.indexOf("ll"));//2
System.out.println(str.indexOf("nihao"));//-1
System.out.println(str.indexOf("o"));//4
5.从指定位置开始查找
包含指定位置开始
public in indexOf(String str,int fromIndex)
6.从指定位置开始判断是否以指定字符开头
System.out.println("nihao".startsWith("h",2)); //true
//从“nihao”的第二个位置开始,判断是否以“h”开头
字符串替换
1.替换所有指定内容
public String replaceAll(String reg,String replace)
2.替换首个指定内容
public String replaceFirst(String reg,String replace)
System.out.println("java is best".replaceAll(" ","-"));
System.out.println("java is best".replaceFirst(" ","-"));
字符串拆分
1.将字符串按照指定格式全部拆分为字符串数组split(String reg)
2.将字符串部分拆分为字符串数组 ,数组长度为limit split(String reg,int limit)
String str="hello java language";
String[] result=str.split(" ");
for(int i=0;i<result.length;i++){
System.out.println(result[i]);
}
//hello
//java
//language
String[] result1=str.split(" ",2);
for(int i=0;i<result1.length;i++){
System.out.println(result1[i]);
}
//hello
//java language
String str="张三:23|李四:23|王五:78";
String[] res=str.split("\\|");//“|”是转义字符,需用\\转义
for(int i=0;i<res.length;i++){
String[] temp=res[i].split(":");
for(int j=0;j<temp.length;j++){
System.out.println(temp[j]);}
}
字符串截取
1.从指定位置截取到结尾
public String substring(int begin);
2.从指定位置开始截取到指定位置结束
public String substring(int start,int ends);//包含start 不包含ends
String str="helloworld";
System.out.println(str.substring(5));//world
System.out.println(str.substring(5,9));//worl
字符串的其他方法
1.去掉字符串的左右空格,保留中间空格
public String trim()
2.字符串转大写
只能转化字母
public String toUpperCase
3.字符串转小写
只能转化字母
public String toLowerCase()
String str=" hello bite !";
System.out.println(str.trim());
str=str+"你好3487&&*&MD";
System.out.println(str.toUpperCase());
System.out.println(str.toLowerCase());
4.取得字符串长度
public int length()
5.判断是否为长度为0的字符串(长度为0 不是null)
public boolean isEmpty()
System.out.println("sssd".isEmpty());//false
System.out.println("".isEmpty());//true
System.out.println(new String().isEmpty());//true
应用:字符串首字母大写
public static String firstUpperCase(String str){
if(str==null||"".equals(str)){
return str;
}else{
if(str.length()==1){
return str.toUpperCase();
}
str=(str.substring(0,1)).toUpperCase()+str.substring(1);
return str;
}
}
2.StringBuffer类
由于String有不可更改的特性,因此提供StringBuffer类,方便字符串的修改,在String中使用"+"来进行字符串连接,但是这个操作在StringBuffer类中需要更改为append()方法:
String与StringBuffer无法相互转换,若想转换:
1.String -->StringBuffer:利用StringBuffer的构造方法或append方法
2.StringBuffer–>String :调用toString()方法
StringBuffer bs=new StringBuffer("java");
bs.append(" is").append(" best");//append方法的链式调用
System.out.println(bs);//java is best
String str=bs.toString()+"!!!";
System.out.println(str);//java is best!!!
String与StringBuffer的相同点:都是字符集(见CharSequence)的接口子类
StringBuffer类特有的方法:
1.字符反转 reverse()
System.out.println(bs.reverse());
2.删除指定范围的数据 delete(int start, int end)
包含start,不包含end
3.插入数据
public synchronized StringBuffer insert(int offset, 各种数据类型 b)
StringBuffer bs=new StringBuffer("java");
System.out.println(bs.insert(0,new StringBuffer( "hi ")));//hi java
System.out.println(bs.insert(0,"hello "));//hello hi java
面试题:请解释String、StringBuffer、StringBuilder的区别:
String是被final修饰的类,不能修改,不能被其他类继承,而StringBuffer、StringBuilder不是,可以修改
StringBuffer采用同步处理,属于线程安全操作(用于多线程项目),而StringBuilder是采用异步处理,属于线程不安全操作(常用于但线程项目)
2.Object类
Object类是所有类的父类,所有类都继承与Object,因此Object可以接收所有对象(基本数据类型、引用数据类型、接口、数组),一些基本方法也是由Object类定义的,因此在其子类中可以覆写
class Student{
private String name;
private int age;
public Student(int age,String name){
this.age=age;
this.name=name;
}
@Override
//覆写Object类中的toString方法
public String toString(){
return "姓名" + this.name + "年龄" + age;
}
}
class Person{}
public class ObjectTest{
public static void main(String[] args){
//Person类没有覆写的toString方法,因此输出是默认的Object中的方法:对象名+地址
ObjectTest.fun(new Person());
//调用覆写过的toString方法
ObjectTest.fun(new Student(18,“name”));
}
//Object类接收对象(引用数据类型)
public static void fun(Object object){
System.out.println(object.toString());
}
}
public static void main(String[] args) {
// Object向上转型,接收int[]数组
Object array1=new int[]{1,2,3,4};
// 需使用数组时需向下转型
int[] array=(int[])array1;
for (int temp:array){
System.out.println(temp);
}
}
equals方法覆写
重写equals方法应遵循的规则:
1.自反性。对于任何非null的引用值x,x.equals(x)应返回true
2.对称性。对于任何非null的引用值x,y,当且仅当:y.equals(x)返回true时,x.equals(y)才应返回true
3.传递性。对于非null的引用值x,y,z,如果x.equals(y)返回true,且y.equals(z)返回true,那么x.equals(z)也应返回true.
4.一致性。对于任何非空引用值x,y假设对象上equals比较信息没有被修改,则多次调用x.equals(y)返回值需一致
5.对于任何非空引用值x.equals(null)应返回false
class Person {
private String name;
private int age;
@Override
public boolean equals(Object obj) {
//若对象没有实例化
if(obj==null){
return false;
}
//若当前对象与传入对象的地址相等
if(this==obj){
return true;
}
//若传入对象的类与当前的Person类不属于同一个类
if(!(obj instanceof Person)){
return false;
}
//排除以上情况,判断传入对象的内容是否相等,相等则返回true
Person person=(Person) obj;
return this.name.equals(person.name) && this.age==person.age;
}
}
Object接收接口
public static void main(String[] args) {
IMesage im=new Mesage();//实现类向接口转型
Object obj=im;//接口向Object转型
im.getMesage();
//Object接收接口的实现类,依然要强制类型转换
Object object=new Mesage();
((Mesage) object).getMesage();
//Object强制类型转化,向下转型
IMesage temp=(IMesage)object;
temp.getMesage();
}
在Java中,利用Object接受一个基本数据类型是可编译可执行的,这是因为基本数据类型会被包装为一个包装类,JVM提供自动装箱机制,将基本数据类型包装,而包装类是Object的子类,因此编译执行提供。
**八种基本数据类型的包装类:**整体被分为对象型和数值型,数值型中,包含六种数值包装类
装箱:将基本数据类型变为包装类对象,可以用包装类的构造方法 或是JVM提供的直接装箱机制。
拆箱:将包装类中的基本数据类型取出,可以用包装类中提供的八种方法或是JVM提供的直接拆箱机制。
public static void main(String[] args) {
//利用构造方法装箱
Integer num=new Integer(12);
//直接装箱
Integer num2=12;
//利用方法拆箱
int num3=num.intValue();
System.out.println(num);//12
System.out.println(num2);//12
System.out.println(num3);//12
//直接拆箱
System.out.println(++num);//13
}
注:在Integer类中采用直接赋值法,[-128,127]区间内的数值创建的相应的对象是在IntegerCache.cache中产生的,若要创建相同的数值,不会另外创建对象,会复用存在这块区域中的已有的对象,若超出这个范围以外的对象,则会重新在堆内存空间上创建对象(无论是否有相同的数值).
public static void main(String[] args) {
Integer num1=12;
Integer num2=12;
Integer num3=153;
Integer num4=153;
Integer num5=new Integer(100);
Integer num6=new Integer(100);
//用==比较的是地址,用equals比较内容(数值)
System.out.println(num1==(num2));//true
System.out.println(num4==(num3));//false
//若采用构造方法赋值装箱的方法,则是会在内存上开辟空间,用==比较的是地址,因此返回false
System.out.println(num5==(num6));//false
}
若将上述"=="判断改为equals则全为true
阿里编码规范:所有相同类型的包装类之间的值比较全部用equals方法进行比较
字符串与基本数据类型的转换:
1.String–>Integer包装类 Integer.parseInt(字符对象)
2.String–>Double包装类 Double.parseDouble(字符对象)
3.String–>Boolean包装类 Boolean.parseBoolean(字符对象)
将字符串转为数字时,若字符串中包含非数字字符,则转换会出错(NumberFormatException);而将字符串转为Boolean不会报此类错误
public static void main(String[] args) {
String string="123.123";
String string1="123";
String string2="true";
String string3="false";
System.out.println(Integer.parseInt(string1));
System.out.println(Double.parseDouble(string));
System.out.println(Boolean.parseBoolean(string2));//true
System.out.println(Boolean.parseBoolean("trues"));//false
}
4.基本数据类型–>字符串
①利用 数值+""
加空白字符串的方式(会产生垃圾空间)
②利用String.valueOf(基本数据类型值)
;(不会产生垃圾空间)
System.out.println(12+"");
System.out.println(String.valueOf(12));
JDK新特性:
在JDK7以后的版本中,对于高位数字,中间可用_分割利于区分数位
System.out.println(1000_000_00);//100000000
若想给int型变量直接赋以二进制表示的值时,在二进制数前加上0b即可
int a=0b10010;
System.out.println(a);//18
String类中+连接字符串的原理
使用+进行字符串连接时,会创建一个临时的StringBuilder对象,该对象调用append方法负责字符串的连接操作,然后再调用StringBuilder类的toString()方法装换成String对象。
若反复执行+操作,内存的开销是非常大的,因此在循环中需要反复连接字符串时,建议采用StringBuilder类的append()方法代替+。
String字符最大长度
在String类中,是使用一个字符数组维护字符序列的,因此String的最大长度取决于数组长度,因为在指定数组长度时可以使用byte、short、char、int而不能使用long,因此数组的最大长度是int类型的最大长度即0x7fffffff,这也是String能容纳的最大字符数量,在获得String对象长度时,返回值类型为int也是这个原因。