案例1 String存储位置介绍:
package com.javaSe.String; /* 重要的信息,在JDK7的时候,就把字符串常量池移动到了堆内存当中了,现在不在方法区了。 关于java JDK中内置的一个类:java.lang.String 1 String表示字符串类型,属于引用数据类型,不属于基本数据类型。 2 在java中随便使用双引号括起来的都是String例如:"abc" "123" "12.3" 这是3个String对象 3 java中规定,双引号括起来的字符串,是不可变得,也就是说"abc",自出生到死亡,不可变,不能变成"abcd"也不能变成"ab"。 4 在JDK当中双括号括起来的字符串,例如:"abc" "123"都是直接存储在“方法区”的字符串“常量池”当中的。 为什么SUN公司把字符串存储在一个字符串常量池当中呢。因为字符串在实际的开发中使用的太频繁。为了执行效率。 所以把字符串放到了方法区的字符串常量池当中。 */ public class StringTest01 { public static void main(String[] args) { // 以下两行代码是在字符串常量池当中创建了3个字符串对象。都在字符串常量池当中。 String s1 = "abc"; String s2 = "abc" + "def"; // 分析:这是使用new的方式创建的字符串对象。这个代码中的"xy"是从哪里来的? // 凡是双引号括起来的都在字符串常量池中有一份 // new对象的时候一定在堆内存中开辟空间 String s3 = new String("xy"); } }
内存图:
案例用户类:
package com.javaSe.String; public class User { private int id; private String name; public User() { } public User(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
用户测试类:
package com.javaSe.String; public class UsetTest { public static void main(String[] args) { User user = new User(111,"张三"); } }
内存图:
String案例2 String s = "" 和 String s1 = new String("")的区别:
package com.javaSe.String; public class StringTest02 { public static void main(String[] args) { String s1 = "hello"; // "hello"是存储在方法区的字符串常量池当中 // 所以这个"hello"不会新建(因为这个对象已经存在了。) String s2 = "hello"; // 分析结果是true还是false? // == 双等号比较的是不是变量中保存的内存地址?是的。 System.out.println(s1 == s2);//true String x = new String("xyz"); String y = new String("xyz"); // 分析结果是true还是false? // == 双等号比较的是不是变量中保存的内存地址?是的。 System.out.println(x == y);//false // 通过这个案例的学习,我们知道了,字符串对象之间的比较不能使用“==” // “==”不保险,应该调用String类的equals方法。 // String类已经重写了equals方法,以下的equals方法调用的是重写之后的equals方法。 System.out.println(x.equals(y));// true String k = new String("testString"); // "testString"这个字符串可以后面加"."呢? // 因为"testString"是一个String字符串对象。只要是对象都能调用方法。 System.out.println("testString".equals(k));// 建议使用这种方式,因为这个可以避免空指针异常。 System.out.println(k.equals("testString"));// 存在空指针异常的风险,不建议这样写。 } }
String案例3 当你使用new String("")创建对象的时候 堆内存中会有几个对象:
package com.javaSe.String; public class StringTest03 { public static void main(String[] args) { /* 一共3个对象: 方法区字符串常量池中有1一个:“hello” 堆内存中有两个String对象。 一共3个 */ String s1 = new String("hello"); String s2 = new String("hello"); } }
String案例4 将byte数组转换成字符串:
package com.javaSe.String; public class StringTest04 { public static void main(String[] args) { // 创建字符串对象最常用的一种方式 String s1 = "hello world!"; // s1这个变量中保存的是一个内存地址。 // 按说以下应该输出一个地址 // 但是输出一个字符串,说明String类已经重写了toString()方法。 System.out.println(s1);//hello world! // 这里只掌握常用的构造方法。 byte[] bytes = {97,98,99};// 97是a,98是b,99是c String s2 = new String(bytes); // 前面说过:输出一个引用的时候,会自动调用toString()方法,默认Object的话会自动输出对象的内存地址。 // 通过输出结果我们得出一个结论:String类已经重写了toString()方法。 // 输出字符串对象的话,输出的不是对象的内存地址,而是字符串本身。 System.out.println(s2); // String(字节数组,数组元素下标的起始位置,长度) // 将byte数组中的一部分转换成字符串。 String s3 = new String(bytes,1,2); System.out.println(s3);// bc // 将char数组全部转换成字符串 // 将char数组的一部分转换成字符串 } }
String案例5: String类中的常用方法:
package com.javaSe.String; import java.sql.SQLOutput; public class StringTest05 { public static void main(String[] args){ // String类当中常用方法 // 1 char charAt(int index) char c = "中国人".charAt(1);// "中国人"是一个字符串String对象。只要是对象就能“.” System.out.println(c);// 国 // 2 (了解).int compareTo(String anotherString) // 字符串之间比较大小不能直接使用 > <,需要使用compareTo(String string)方法。 int result = "abc".compareTo("abc"); System.out.println(result);// 0 (等于0) 前后一致 10 - 10 = 0 int result2 = "abcd".compareTo("abce"); System.out.println(result2);// -1(小于0) 前小后大 8 - 9 = -1 int result3 = "abce".compareTo("abcd"); System.out.println(result3);// 1(大于0) 先大后小 9 - 8 = 1 // 拿着字符串第一个字母和后面字符串的第一个字母比较。能分胜负就不再比较了。 System.out.println("xyz".compareTo("yxz")); //-1 // 3 (掌握).boolean contains(CharSequence s) // 判断前面的字符串中是否包含后面的字符串。 System.out.println("HelloWorld.java".contains(".java"));// true System.out.println("http://www.baidu.com".contains("https://"));// false // 4 (掌握) .boolean endsWith(String suffix) // 判断当前字符串是否以某个子字符串结尾。 System.out.println("test.txt".endsWith(".java"));// false System.out.println("test.txt".endsWith(".txt"));// true System.out.println("sdfhkshfsdkhfksdh".endsWith("dh"));// true // 5 (掌握) .boolean equals(Object anObject) // 比较两个字符串必须使用equals()方法,不能使用"==" // equals()方法有没有调用compareTo()方法?老版本可以看一下。JDK13中并没有调用compareTo()方法。 // equals只能看出两个字符串之间是否相不相等 // compareTo方法可以看出是否相等,并且同时还可以判断谁大谁小。 System.out.println("abc".equals("abc"));// true // 6(掌握) .boolean equalsIgnoreCase(String anotherString) // 判断两个字符串是否相等,并且忽略大小写。 System.out.println("AbC".equalsIgnoreCase("abc"));//true // 7 (掌握) byte[] getBytes() // 将字符串对象转换成字节数组 byte[] b = "abcdef".getBytes(); for(int i = 0; i < b.length ; i++){ System.out.println(b[i]); } // 8 (掌握) int indexOf(String str) // 判断某个子字符串在当前字符串中第一次出现的地方的索引(下标)。 System.out.println("orcalejavac++.netc#phppythonjavaorcalec++".indexOf("java")); // 6 // 9 (掌握) boolean isEmpty() // 判断某个字符串是否为空的字符串 底层源代码调用的应该是字符串的length()方法。 // 不是null哦 null的话会引起空指针异常哦 String s = ""; System.out.println(s.isEmpty());// true // 10(掌握) int length() // 面试题:判断数组长度和判断字符串长度不一样。 // 判断数组长度是length属性。判断字符串长度是length()方法。 System.out.println("abc".length());// 3 System.out.println("".length());// 0 // 11(掌握) int lastIndexOf(String str) // 判断某个子字符串在当前字符串中最后一次出现的索引(下标) System.out.println("orcalejavac++javac#phpjavapython".lastIndexOf("java")); // 22 // 12(掌握) String replace(CharSequence target, CharSequence replacement) // 替换的意思。 // String的父接口就是:CharSequence System.out.println("http://www.baidu.com".replace("http://","https://")); // https://www.baidu.com // 把以下字符串中的“=”替换成“:” System.out.println("name=zhangsan&passworld=123&age=20".replace("=",":"));//name:zhangsan&passworld:123&age:20 // 13(掌握) String[] split(String regex) // 拆分字符串 String[] ymd = "1980-10-11".split("-");// "1980-10-11"以"-"分隔符进行拆分。 for (int i = 0; i < ymd.length; i++) { System.out.println(ymd[i]); } String param = "name=zhangsan&passworld=123&age=20"; String[] params = param.split("&"); for (int i = 0; i < params.length; i++) { System.out.println(params[i]); // 可以继续向下拆分,可以通过"="进行拆分 String[] s1 = params[i].split("="); for (int j = 0; j < s1.length; j++) { System.out.println(s1[j]); } } // 14(掌握) boolean startsWith(String prefix) // 判断某个字符串是否以某个子字符串开始 System.out.println("http://www.baidu.com".startsWith("http"));//true System.out.println("http://www.baidu.com".startsWith("https"));//false // 15(掌握) String substring(int beginIndex) 参数是起始下标 // 截取字符串 System.out.println("http://www.baidu.com".substring(7)); // www.baidu.com // 16(掌握) String substring(int beginIndex, int endIndex) // 从第一个下标开始 以endIndex - 1处停止。 // beginIndex起始位置(包括) // endIndex结束位置(不包括) System.out.println("http://www.baidu.com".substring(7,10));// www // 17(掌握)char[] toCharArray() // 将字符串转换成char数组 char[] chars = "我是中国人".toCharArray(); for (int i = 0; i < chars.length; i++) { System.out.println(chars[i]); } // 18(掌握) String toLowerCase() // 转换为小写 System.out.println("ABFDJKFH".toLowerCase()); // abfdjkfh // 19(掌握) String toUpperCase() System.out.println("abfdjkfh".toUpperCase()); // ABFDJKFH // 20(掌握) String trim(); // 去除字符串前后空白 中间的空白不会去除 System.out.println(" Hello World ".trim()); // Hello World // 21(掌握) String中只有一个方法是静态的,不需要new对象 // 这个方法叫做valueOf // 作用:将“非字符串”转换成“字符串” // String s1 = String.valueOf(true); // "true" String s1 = String.valueOf(100); // "100" System.out.println(s1); // 这个静态的valueOf()方法,参数是一个对象的时候,会自动调用该对象的toString()方法吗? String s2 = String.valueOf(new Customer()); // System.out.println(s2); // 没有重写toString()方法之前是对象内存地址 "com.javaSe.String.Customer@10f87f48" System.out.println(s2); // 我是一个VIP客户!!! // 我们是不是可以研究一下println()方法的源代码了? System.out.println(100); System.out.println(3.14); System.out.println(true); // 通过源代码可以看出:为什么输出一个引用的时候,会调用toString()方法!!!! // 本质上System.out.println()这个方法在输出任何数据的时候都是先转换成字符串,在输出。 System.out.println(new Object()); System.out.println(new Customer()); } } class Customer{ // 重写toString()方法 @Override public String toString() { return "我是一个VIP客户!!!"; } }