扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
常用的3种方式:
10年积累的网站设计、成都网站设计经验,可以快速应对客户对网站的新想法和需求。提供各种问题对应的解决方案。让选择我们的客户得到更好、更有力的网络服务。我虽然不认识你,你也不认识我。但先做网站后付款的网站建设流程,更有亳州免费网站建设让你可以放心的选择与我们合作。public class test7 {public static void main(String[] args) {String s1="qwdj1238385";//直接创建;编译器会根据值创建对象
String s2=new String("nfihwj2393-");//通过构造方法创建
char []arr={'a','s','c'};//字符数组
String s3=new String(arr);
System.out.println(s3);//输出asc
//java的字符串是不会像c语言那样后面有个/0结尾
}
}
字符串内存储存(不涉及常量池理解)先简单认识一下String源码:
调试一下,可以看到确实是如此。
String是引用类型里边并不储存字符串,而是储的它的引用。
先简单理解一下,不介绍常量池概念;new对象的方式储存。
当我们创建String s2=s1时,他们指向同一个引用。
1:是否相等
引用类型的比较不能使用 = =;得使用equals方法。
数组是Object对象,如果直接使用equals方法,实质上还是使用==比较。我们的String,Arrays类都重写了equles方法。
import java.util.Arrays;
public class test7 {public static void main(String[] args) {String s1="qqq";
String s2=new String("qqq");
System.out.println(s1==s2); //false
System.out.println(s1.equals(s2)); //true
System.out.println(s1.equalsIgnoreCase(s2));//忽略大小写比较
int []arr1={1,2,3};
int []arr2={1,2,3};
System.out.println(arr1==arr2); //false
System.out.println(arr1.equals(arr2)); //false
System.out.println(Arrays.equals(arr1,arr2)); //true
}
}
2:比较大小
String已经实现Comparable接口且重写compareTo方法
所以我们直接使用就行;返回int 类型,他们的差值。是先比较第一个,如果第一个相等就继续比较第二个字符。直到比完如果相等就返回0。
public class test8 {//字符串的比较大小
public static void main(String[] args) {String s1="abe";
String s2=new String("abc");
System.out.println(s1.compareTo(s2)); //2
}
}
如果是前面都相等的情况下,那么谁的字符个数多则比较大。返回相差的字符个数字符
public class test8 {public static void main(String[] args) {String s1="abceeee";
String s2=new String("abc");
System.out.println(s1.compareTo(s2)); //4
System.out.println(s1.compareToIgnoreCase(s2));//忽略大小写比较
}
}
字符串查找1:从前往后找
public class test9 {//查看字符串
public static void main(String[] args) {String s1="abccdefg";
System.out.println(s1.indexOf('p'));//在字符串查找某个字符的位置,如果没有返回-1
System.out.println(s1.indexOf('c',3));//从下标为3开始找
System.out.println(s1.indexOf("bcc")); //查找字符串的位置
System.out.println(s1.indexOf("bcc",3)); //从3下标开始查找字符串的位置
}
}
2:从后往前找
public class test9 {//查看字符串
public static void main(String[] args) {String s1="abccdefg";
System.out.println(s1.lastIndexOf('c'));
System.out.println(s1.lastIndexOf('c',5)); //从5下标开始往前找
System.out.println(s1.lastIndexOf("abc"));
System.out.println(s1.lastIndexOf("ajff",5)); //从5下标开始往前找
}
}
转化为字符串类型public class test10 {public static void main(String[] args) {//类名调用,static方法
String s1=String.valueOf(123);//数字转字符
System.out.println(s2);//123
String s2=String.valueOf(new student(18,"str"));
System.out.println(s2); //这时候打印是地址,没转化成功
}
}
class student {int age=100;
String name;
}
转化的前提是得重写了tostring方法。源码是如果自己没有重写toString方法它则去调用Object的。
重写的代码:(步骤:鼠标右键,Generate,选择toString)
@Override
public String toString() {return "student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
重写后输出结果:
字符串类型转成其它类型
public class test11 {public static void main(String[] args) {int a1=Integer.parseInt("123"); //转int类型
int a2=Integer.valueOf("123");
double a3=Double.parseDouble("12.3");//其它类型都是类似方法
}
}
大小写的英文字母互相转换
public class tset12 {public static void main(String[] args) {String s="abc";
String s1=s.toUpperCase();//小转大
System.out.println(s);
System.out.println(s1);
String s3=s1.toLowerCase();//大转小
System.out.println(s3);
}
}
输出:
abc
ABC
abc
注意:String 类是不可改变的,所以你一旦创建了 String 对象,那它的值就无法改变了,我们并不是在原来的那一份上修改。
字符串转数组public class test13 {public static void main(String[] args) {String s1="1ewjdh";
String s2="djff";
char []arr1=s1.toCharArray();
}
}
格式化字符串(使用比较少)推荐参考
public class test13 {public static void main(String[] args) {String s1 = "abcccddecdg";
String s2 = s1.replace('c', 'd');//把所有的c换成d
System.out.println(s2);
String s3 = s1.replace("cd", "sb");//把所有的cd换成sb
System.out.println(s3);
String s4 = s1.replaceAll("cd", "sb");//也是把所有的cd换成sb,这个方法得是字符串才能用
System.out.println(s4);
String s5 = s1.replaceAll("c", "d");
System.out.println(s5);
String s6=s1.replaceFirst("cd","sb");//把第一个出现的cd换成sb,也是只能用字符串
System.out.println(s6);
}}
输出结果:
abdddddeddg
abccsbdesbg
abccsbdesbg
abdddddeddg
abccsbdecdg
把一个完整的字符串按照指定的分隔符划分为若干个子字符串;返回的结果是字符串数组。
import java.util.Arrays;
public class test14 {public static void main(String[] args) {String s1="wnjksnaasjeda";
String []arr=s1.split("s");
String []arr1=s1.split("s",2);//设置只划分为两个子字符串
System.out.println(Arrays.toString(arr));
char [] a={'1','2'};
System.out.println(a);
}
}
特殊情况:需要加转义字符。
import java.util.Arrays;
public class test14 {public static void main(String[] args) {String s1="127.123.455";
String []arr=s1.split("\\.");
System.out.println(Arrays.toString(arr));
}
}
转义字符也需要转义字符来修饰,所以就是两个\最终发挥一个作用。如果我们要使用\来划分就需要\\(| * +都得需要转义字符)
多个分隔符的情况。使用| 分隔开
import java.util.Arrays;
public class test14 {public static void main(String[] args) {String s1="127.123.4&55";
String []arr=s1.split("\\.|&");
System.out.println(Arrays.toString(arr));
}
}
输出:[127, 123, 4, 55]
字符串截取public class test12 {public static void main(String[] args) {String s1="helooworld";
String s2=s1.substring(5);//从5位置往后截取
System.out.println(s2);
String s3=s1.substring(5,9);//截取【5-10)区间字符
System.out.println(s3);
}
}
输出:
world
worl
public class test12 {public static void main(String[] args) {String s1=" hel ooworld ";
String s2=s1.trim();
System.out.println(s2);
}
}
输出:hel ooworld
判断字符串是否包含字符串public class test12 {public static void main(String[] args) {String s1=" hel ooworld ";
System.out.println(s1.contains("h"));//true
}
}
判断以…字符串开始public class test12 {public static void main(String[] args) {String s1="hel ooworld ";
System.out.println(s1.startsWith("hel"));//判断是否从这个字符串开始
}
}
不得不说这个字符串类型你能想到的字符串操作,他都有实现的方法,并且这个字符串类型是非常的重要,我们在做练习的时候大部分的题不是操作数组就是操作字符串。需要用到其它方法的时候 官方文档查看
字符串内存储存(涉及常量池理解)字符串常量池在堆里边;底层是一个StrinTable哈希表(数组与链表的组合)。
字符串到底怎么储存的?为什么会出现下面的状况????
public class test15 {public static void main(String[] args) {String s1="hello";
String s2="hello";
System.out.println(s1==s2);//true
System.out.println(s1.equals(s2));//true
String s3=new String("hello");
System.out.println(s1==s3);//false
System.out.println(s1.equals(s3));//true
}
}
String s1="hello"; String s2="hello";
我们直接使用第一种创建方式,它是先去字符串常量池看有没有这个字符串。如果有就不放进常量池,没有才添加进去。
只要是这种双引号的" 对象"在字符串常量池存过就不会再存第二份相同的。具体看下图分析。(基于java8)
第二次创建的时候,他们的value是相同的,因为这个数组只会有一份。
值相同,String对象存的也相同。
new 对象的情况:创建一个新的String对象。但是它里面的value是一样的,因为这个"hello"始终只有一份。值是相同的,但是String对象是不同的。
题目1:
题目2:
题目3:
“abc”+“def"编译的时候就是相当于"abcdef”,所以4执行,6不执行。
intern 是一个native方法(Native方法指:底层使用C++实现的,看不到其实现的源代码),该方法的作用是手
动将创建的String对象添加到常量池中。
public static void main(String[] args) {char[] ch = new char[]{'a', 'b', 'c'};
String s1 = new String(ch); // 将ch数组再拷贝一份,然后到String对象中,s1对象并不在常量池中,
s1.intern(); // s1.intern();调用之后,会将s1对象的引用放入到常量池中
String s2 = "abc"; // "abc" 在常量池中存在了,s2创建时直接用常量池中"abc"的引用
System.out.println(s1 == s2); //输出true
}
三种创建方式内存不同的总结:
String str = “hello”:在堆开辟一块内存空间,然后保存到字符串常量池,再给String引用。创建两个对象数组+String对象
String str = new String(“hello”) : 会开辟两块堆内存空间,字符串"hello"保存在字符串常量池中,然后用常量池中的String对象给新开辟
的String对象赋值。创建3个对象(常量池没有的情况)
String str = new String(new char[]{‘h’, ‘e’, ‘l’, ‘l’, ‘o’}) :现在堆上创建一个String对象,然后利用copyof将重新开辟数组空间,将参数字符串数组中内容拷贝到String对象中(把hello字符数组拷贝一份给String)。创建数组,数组的拷贝,String对象
(char数组是不会直接放入常量池的,在这个构造中:this.value = Arrays.copyOf (value, value.length),是对实参变量做了拷贝,存储在堆中)
1:我们操作的字符串原来的是不会改变的,都是新建。看一下源码分析。
不建议在String类型对象进行修改,因为每一次修改都会创建很多对象.
public class test22 {public static void main(String[] args) {String s1="hello";
s1+="world";
}
} //一个简简单单拼接光String对象就创建了3给个(hello,world,helloworld)
可以看到两个代码的时间差别是非常的大
1 :StringBuilder和StringBuffer类。这两个类大部分功能是相同的
2 :String和StringBuilder大的区别在于String的内容无法修改,而StringBuilder的内容可以修改。频繁修改字符串的情况考虑使用StringBuilder。
public class test22 {public static void main(String[] args) {StringBuffer s=new StringBuffer("abc");
long start=System.currentTimeMillis();
for (int i = 0; i<100000 ; i++) { s.append(i);//追加i字符串
}
long end=System.currentTimeMillis();
System.out.println(end-start);//13
}
}
两者之间转换:
String变为StringBuilder: 利用StringBuilder的构造方法或append()方法
StringBuilder变为String: 调用toString()方法。
String str = "abcde";
StringBuilder str0 = new StringBuilder(str);
String str = "abcde";
StringBuilder str0 = new StringBuilder();
str0.append(str);
str = s1.toString();
StringBuilder官方文档
String、StringBuffer、StringBuilder的区别
1: String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.
2: StringBuffer与StringBuilder大部分功能是相似的
3: StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流