- indexOf()
- int start = indexOf(".");------------------------判断该字符第一次出现的位置,从0开始
- 重载:indexOf("." , start);----从start位置开始
- lastIndexOf(".");-------------------判断该字符最后一次出现的位置
- 检索当前字符串中给定字符串的位置,如果当前字符串不包含给定内容时返回值为-1
- 验证字符串给定字符是否唯一
public static void main(String[] args) {
//indexOf除了检索位置 还可以做一些验证的操作
String str = "xxxxx@qq.com";
//输入时候判断@输入了几次
int first = str.indexOf("@");
int last = str.lastIndexOf("@");
int index = str.indexOf("s");
System.out.println(index);//-1 因为不存在
if(first == last){
System.out.println("@ 一共输入了一次,可以继续");
}else{
System.out.println("@ 输入了多次,不合法");
}
}
- String substring(int start,int end)
- 截取当前字符串中指定范围内的字符串
- start开始,end结束
- 在java API中通常使用两个数字表示范围时,都是含头不含尾的
public static void main(String[] args) {
String str = "www.baidu.cn";
System.out.println(str.indexOf("."));//3
System.out.println(str.substring(4,str.lastIndexOf(".")));//baidu
//重载的subString方法可以从指定位置截取到字符串末尾
System.out.println(str.substring(4));
}
public static void main(String[] args) {
String name1 = getHostName("www.xiaocui.cn");
String name2 = getHostName("http://doc.xiaocui.org");
String name3 = getHostName("www.xiaocui.com.cn");
}
public static String getHostName(String name){
int start = name.indexOf(".")+1;
int end = name.indexOf(".",start);
String str = name.substring(start,end);
System.out.println(str);
return str;
}
//xiaocui
//xiaocui
//xiaocui
- int length()
- 返回当前字符串的长度(字符个数)
- 字符串当中length()是个方法,需要带括号
- 数组中的length不是方法,是属性,不需要带括号
public static void main(String[] args) {
String str = "我爱 java";
System.out.println(str.length());//从1开始
}
- char charAt(int index)
- 返回当前字符串中指定下标对应的字符
- 验证回文
- 立一个flag、void return; 实现的方法很多
public static void main(String[] args) {
String str = "Thinking in java";
char c = str.charAt(5);
System.out.println(c);//i 从下标0开始
//验证回文
String s = "上海自来水来自海上";
boolean flag = true;
for(int i=0;i<4;i++){
char a = s.charAt(i);
char b = s.charAt(s.length()-i-1);
if(a != b){
System.out.println("不是回文");
flag = false;
//return; //这里直接就跳出方法了不再走下面的语句了
break;
}
}
if(flag){
System.out.println("是回文");
}
}
public static void main(String[] args) {
String str = " Think in java ";
System.out.println(str);
System.out.println(str.trim());//只能去除两边的,中间的不管用
}
- boolean startsWith(String str)
- boolean endsWith(String str)
public static void main(String[] args) {
String str = "www.tedu.com";
System.out.println(str.startsWith("www."));
System.out.println(str.endsWith(".com"));
}
- String toUpperCase()
- String toLowerCase()
public static void main(String[] args) {
String str = "我爱java!";
System.out.println(str.toUpperCase());
System.out.println(str.toLowerCase());
}
- String.valueOf()
- String提供了一组重载的valueOf()方法,作用是将其它类型转换为字符串类型
- 注:这些valueOf都是静态方法
public static void main(String[] args) {
int a = 123;
String s = String.valueOf(a);//性能好
String s1 = a+"";//加个空串也能转字符串
System.out.println(s);
System.out.println(s1);
}
- String
- 常量池:字面量创建的过的字符串对象
- new:new了必创建对象,String 可以new 但是不建议,没有意义
- == 和 equals的区别,==比的是地址,equals比的是值
- 编译器:如下代码块注释
- 字符串被final修饰,不可改变
- 创建对象 new + 构造方法();
- 字符串有个常量池,在堆中(使用字面量创建过的字符串对象)
- 当我们创建字符串的时候,会先去常量池里找有没有这个字符串对象,没有的话就创建这个对象
- 有的话,就会把它的地址 交给该String的引用,这样,该String就有了相同的地址
- 判断:
- 判断字符串内容相等用equals,别的引用类型需要重写equals()方法才可用equals比较相等,字符串特殊,直接用Object方法就可以
- 判断字符串内容是否为空,用 isEmpty();
public static void main(String[] args) {
String stu1 = "123abc";
/**由于stu1使用该字面量创建过字符串对象,因此stu2和stu3会重用这个对象*/
String stu2 = "123abc";
System.out.println(stu1 == stu2);//true 地址相同
stu2 = stu2+"!";//修改、拼接字符串内容,会创建新对象
System.out.println(stu2);
System.out.println(stu1 == stu2);//false 双 == 比较的是地址
String stu4 = new String("123abc");
System.out.println(stu1 == stu4);//false 地址不同,new 代表创建了新的对象
System.out.println(stu1.equals(stu4));//true,equals比较的是内容,内容相同
/**
* 这里触发了编译器的一个特点:
* 编译器在编译源代码时,只要一个计算表达式可以在编译期间确定结果的,
* 编译器一定进行计算,并将结果编译到字节码文件中,因此下面的代码会被编译器改为:
* String s5 = "123abc";
* 因此s5在JVM进行执行时会重用s1对象
*/
String s5 = "123"+"abc";
System.out.println(stu1 == s5);//true 编译器在编译时,会自动将直接量计算
String s6 = "a123";
String s7 = s6 + "abc";//变量不会自动计算,而且拼接的字符串不会存在常量池里
System.out.println(s7 == stu1);//false 修改字符串内容,创建新对象,
String s8 = "a123abc";
System.out.println(s7 == s8);//拼接的字符串不会存在常量池里
}
- 字符串连接操作问题
- System.out.println(6 + 6 + "(Result)");=>12(Result):如果第一个和第二个…..第 n 个都是基本数据,第 n+1 是字符串类型,那么前 n 个都按加法计算出结果在与字符串连接
- System.out.println("(Result)" +6 + 6 );=>(Result)66 :字符串与基本数据类型链接的问题,如果第一个是字符串那么后续就都按字符串处理
- 常量池问题
public class Test {
public static void main (String [] args) {
String foo = "blue";
String bar = foo;
foo = "green";
System.out.println(bar); //blue
}
}
String foo = "blue"定义方式定义的字符串放在字符串池中,通过 String bar = foo;他们指向了同一地址空间,就是同一个池子,当执行 foo = "green"; foo 指向新的地址空间。
- 注意:String类型变量取值应为小写null或其他用""双引号括起来的内容 :String str = NULL; //编译不通过
- String方法接收得问题
public class Base{
private void test() {
String aStr = "? One? ";
String bStr = aStr;
aStr.toUpperCase();
aStr.trim();
System.out.println("[" + aStr + "," + bStr + "]");
}
static public void main(String[] a) {
new Base().test(); //[? One? ,? One? ]
}
}
通过 String bStr = aStr;这句代码使 bStr 和 aStr 指向同一个地址空间,所以最后 aStr 和 bStr 的结 果应该是一样,String 类是定长字符串,调用一个字符串的方法以后会形成一个新的字符串。
在调用toUpperCase()和trim()方法时都会返回新的字符串对象,
而上述中在调用完这两个方法后并没有使用变量接收方法所返回的新字符串对象,而aStr和bStr所引用的仍然是原来的字符串对象。
- 字符串:一个引用只能指向一个对象,一个对象可以被多个引用指向
- String、普通引用类型和基本类型作为形参传递
- 形参:方法声明时包含的参数声明
- 实参:调用方法时,实际传给形参的参数值
- Java方法的参数传递:值传递==>就是将实际参数值的副本,传入方法内,而参数本身不会受到任何影响。
- String是不可改变的,改变必创建新的对象
- 引用类型也是采用值传递方式。但是使用对象引用时,容易发生误解,因为它能够交换成功。
- 基本类型作用在形参时,方法里操作的并不是实际的实参变量
- 案例如下:String类型当作形参时:实参传入的是地址,形参接受的也是地址,可以理解为:形参的操作与实参无关,除非方法this.实参,形参new了一个新的对象,就会分配一个新的地址
- 数组属于普通引用类型,传入的也是地址,普通引用类型,改变值不会创建新得对象,除非新new
- 引用类型和基本类型传入得都是变量,而引用类型得变量存放得是地址!
- 注意:
- 方法的参数也是局部变量,引用类型实参传的是地址,形参接收的也是地址
- 基本类型实参传的是值,接收的也是值
//String类型
public class Example{
String str="good";
char[]ch={'a','b','c'};
public static void main(String args[]){
Example ex=new Example();
ex.change(ex.str,ex.ch);
System.out.print(ex.str+" and "); //good and
System.out.print(ex.ch); //gbc
}
public void change(String str,char ch[]){
//每一个String类型的对象都指向常量池中的一个地址
//但是它的特殊点是,String类型的值改变,地址就会改变
//改变必创建新对象,意味着必会分配一个新的地址
//地址传过来后,相当于new了一个新的对象分配了一个新的地址给这个局部变量的str,局部变量得作用域随着方法得调用而存在,方法得结束而释放
//str无关
str="test ok";
ch[0]='g';
}
}
一个引用只能指向一个对象,一个对象可以被多个引用指向。
除非你改变构造函数的形参名字或使用this.name来访问成员
//如下
public void change(String str,char ch[]){
//每一个String类型的对象都指向常量池中的一个地址
//但是它的特殊点是,String类型的值改变,地址就会改变
//改变必创建新对象,意味着必会分配一个新的地址
//这里修改的成员变量的地址,也创建了一个新的对象,good相当于就没有地址了,成为了垃圾
//数据,新的地址指向了 test ok
this.str="test ok"; //这里改变得是成员变量,局部变量没有被调用
ch[0]='g';
}
//普通引用类型
public class Question {
private int num;
public static void main(String [] args){
Question q = new Question();
q.num=13;
update(q);
System.out.println(q.num); //9
}
public static void update(Question q){
q.num=9;
}
}
普通的引用类型作为形参传递时,改变不会创建新的对象
------------------------------------------------------------
如果形参方法创建了新的对象,那么就是创建了一个新的对象,分配了一个新的地址,指向形参q
此时形参中的q 和实参中得q指向的地址就不是一个地址了,所以此时main输出的就是13
public class Question {
private int num;
public static void main(String [] args){
Question q = new Question();
q.num=13;
update(q);
System.out.println(q.num); //13
}
public static void update(Question q){
q = new Question(31);
}
}
public class Question {
public static void main(String[] args) {
int a = 1;
int b = 2;
Question.speed(a, b);
System.out.println("a="+a+",b="+b);//1,2
}
//方法里是得都是方法得局部变量
//基本类型 没有地址的改变 操作与别人无关
public static void speed(int a,int b){
int temp = a ;
a = b;
b = temp;
System.out.println("a="+a+",b="+b); //2,1
}
}