Java笔记
包装类
Wrapper(包装器)
定义
针对八种基本的数据类型类型响应的引用类型
有类的特点,可以调用类的方法
除了 int -> Integer char- > Character 其余的六个都是将首字母大写就是对应的包装类
Boolean Byte Short Long Float Double
Boolean 与 Character 二者是实现了比较和可序列化的接口的Object子类
1 2
| public final class Boolean implements java.io.Serializable, Comparable<Boolean>
|
1
| class Character implements java.io.Serializable, Comparable<Character>
|
而这些数字的类型一般都是继承了Number类,而Number类是实现了可序列化的接口的Object子类,数字类型直接实现比较接口
图标如下

装箱与拆箱
自动拆装箱,本质上和手动没有区别,由编译器自动调用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class WrapperType { public static void main(String[] args) { int i = 10; Integer pack = new Integer(i); Integer pack2 = Integer.valueOf(i);
int j = pack.intValue();
int k = 200; Integer pack3 = k; int k1 = pack3; }
|
一道比较经典的面试题目

包装类型和String转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class WrapperType { public static void main(String[] args) { Integer i = 127; String s1 = i + ""; String s2 = i.toString();
System.out.println(s1);
Integer i1 = Integer.parseInt(s1); Integer i2 = Integer.valueOf(s1);
System.out.println(i2); } }
|
一些常用的方法
即查即用,不用特殊记忆
返回最小值 最大值
1 2 3 4 5 6 7
| public class WrapperType { public static void main(String[] args) { Integer i = 127; System.out.println(i.MIN_VALUE); System.out.println(Integer.MIN_VALUE); } }
|
判断是不是数字,是不是字母,是不是大写,是不是小写,是不是空格,转成大写,转成小写(查询使用即可,或者可以自己实现)
Integer的面试题
之前也涉及到过,在前面的数据类型中我曾写过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class WrapperType { public static void main(String[] args) { Integer i1 = new Integer(12); Integer i2 = new Integer(12); System.out.println(i1 == i2); Integer i3 = 12; Integer i4 = 12; System.out.println(i3 == i4); Integer i5 = 128; Integer i6 = 128; System.out.println(i5 == i6); } }
|
1 2 3 4 5
| public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
|
存在一个cache,-128—127,在范围外才会创建对象
已经静态的创建好了一个Integer包装数组,将-128—127,在范围内直接用引用指向即可
还有一个,这里涉及到的是基本数据类型,比较的是值是否相等

String
定义
支持可序列化接口,比较接口,可读的字符序列接口
1 2
| public final class String implements java.io.Serializable, Comparable<String>, CharSequence { ... }
|
1.String 对象是用来保存字符串的,是一组字符序列
2.字符串常量对象使用双引号括起的字符序列
3.字符串的字符使用的是Unicode字符编码,一个字符占用两个字节
4.String类较为常用的构造方法有以下:多种构造器
1 2 3 4 5 6 7 8 9
| ()
(String original)
(char[] a)
(char[] a, int startIndex, int count)
(byte[] b)
|
String 有属性private final char value[ ] :用于存储字符串内容,final代表value指向的地址不可以被修改(而地址存储的单个字符内容可以变化),以下是一个代码示例
1 2 3 4 5 6 7 8
| public class String1 { public static void main(String[] args) { final char[] target = {'1','2','5'}; target[0] = '4'; char[] target1 = {'1','2','3'}; } }
|
创建String对象方式
1 2 3 4 5 6
| public class String1 { public static void main(String[] args) { String str1 = "abc"; String str2 = new String("abc"); } }
|
方式一:查看常量池中是否有”abc”的数据空间,如果有直接指向,如果没有则在常量池中创建,最后指向的是常量池中的空间地址
方式二:在堆中创建空间,如果里面维护了value属性,指向常量池中的”abc”空间,如果常量池中没有”abc”重新创建,如果有直接通过value指向,最终指向的是堆中的空间地址,堆中的引用指向常量池中的地址
以下是示例图片

虽然指向的最终都是到常量池中的字符,但是二者指向的第一个地址不一样(一个在堆中,另一个在常量池中)
1 2 3 4 5 6 7
| public class String1 { public static void main(String[] args) { String str1 = "abc" String str2 = new String("abc"); System.out.println(str1 == str2); } }
|
调用intern方法时,如果常量池中已经包含了对应的字符串,就返回池中的字符串地址,否则先添加String对象添加到池中,并返回池中的地址
一个测试题目

最后一个e指向常量池,true,优化为e = “helloabc”;
String的常用方法
equals
//判断是否相等
1 2 3
| String str1 = new String("abc"); String str2 = new String("abccdff"); System.out.println(str1.equals(str2));
|
equalsIgnoreCase
//忽略大小写判断是否相等
1 2 3
| String str1 = new String("abc"); String str2 = new String("ABC"); System.out.println(str1.equalsIgnoreCase(str2));
|
length
//字符个数,字符串长度
1
| System.out.println(str1.length());
|
indexOf
//获取第一个对应对应字符的索引,无则返回-1
注意可以传入字符串
1 2
| System.out.println(str1.indexOf("bc")); System.out.println(str2.lastIndexOf('B'));
|
lastIndexOf
//获取最后一个对应字符的索引,无则返回-1
同上类似
substring
//截取指定范围的字串
一个参数
1 2 3 4 5 6 7 8 9 10
| public String substring(int beginIndex) { if (beginIndex < 0) { throw new StringIndexOutOfBoundsException(beginIndex); } int subLen = value.length - beginIndex; if (subLen < 0) { throw new StringIndexOutOfBoundsException(subLen); } return (beginIndex == 0) ? this : new String(value, beginIndex, subLen); }
|
两个参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public String substring(int beginIndex, int endIndex) { if (beginIndex < 0) { throw new StringIndexOutOfBoundsException(beginIndex); } if (endIndex > value.length) { throw new StringIndexOutOfBoundsException(endIndex); } int subLen = endIndex - beginIndex; if (subLen < 0) { throw new StringIndexOutOfBoundsException(subLen); } return ((beginIndex == 0) && (endIndex == value.length)) ? this : new String(value, beginIndex, subLen); }
|
concat
//拼接字符串
1
| System.out.println(str1.concat(str2));
|
replace
//替换字符串
1
| System.out.println(str1.replace("a", "b"));
|
toUpperCase
//向上取大写
1
| System.out.println(str1.toUpperCase());
|
toLowerCase
//取向下小写
1
| System.out.println(str2.toLowerCase());
|
split
//以()为标准分割字符串内容
转移字符需要在前加 \
1 2 3 4
| String str3 = new String("abc,ABe,CDE"); String[] stringArr = str3.split(","); String str4 = stringArr[0]; System.out.println(str4);
|
toCharArray
//转换为字符数组
1 2
| char[] a = str1.toCharArray(); System.out.println(a[1]);
|
compareTo
//比较大小
1 2 3
| String str1 = new String("abc"); String str2 = new String("ABC"); System.out.println(str1.compareTo(str2));
|
当区分不出大小且,长度不一样时有不同返回值,详见源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public int compareTo(String anotherString) { int len1 = value.length; int len2 = anotherString.value.length; int lim = Math.min(len1, len2); char v1[] = value; char v2[] = anotherString.value;
int k = 0; while (k < lim) { char c1 = v1[k]; char c2 = v2[k]; if (c1 != c2) { return c1 - c2; } k++; } return len1 - len2; }
|
trim
//去前后空格
1 2
| String str1 = new String(" ab c "); System.out.println(str1.trim());
|
//字符串格式化拼接
类似于C语言中printf
1 2 3 4
| String str1 = new String("abc"); String str2 = new String("ABC"); String str3 = String.format("你好 %s 和 %s", str1, str2); System.out.println(str3);
|
有点太多了,没必要全记,记不得在查,早晚会熟练使用的
StringBuffer
定义
是一种增强的String支持增删改,直接父类是AbstractStringBuilder,实现了可序列化的接口,是一个final类型,不可被继承

1 2
| abstract class AbstractStringBuilder implements Appendable, CharSequence { char[] value;
|
其中有value char数组,存放在堆中
StringBuffer相较于String保存的字符串常量(值无法修改),StringBuffer不用在修改内容的时候更改地址(除非内存不足时重新扩容复制),所以效率上高于String
常用的构造器
默认的无参构造器(创建一个16字符的空间)
1 2 3 4 5
| public class StringBuffer01 { public static void main(String[] args) { StringBuffer sb = new StringBuffer(); } }
|
传入int参数构造器,其中容量为32个字符
1 2 3 4 5
| public class StringBuffer01 { public static void main(String[] args) { StringBuffer sb = new StringBuffer(32); } }
|
传入String常量
1 2 3 4 5
| public class StringBuffer01 { public static void main(String[] args) { StringBuffer sb = new StringBuffer("StringBuffer01"); } }
|
jdk源码,其中先new一个同样大小的数组,再通过append拼接+16的容量
1 2 3 4
| public StringBuffer(String str) { super(str.length() + 16); append(str); }
|
1 2 3
| AbstractStringBuilder(int capacity) { value = new char[capacity]; }
|
与String的转化
转为String
1 2 3 4 5 6 7 8
| public class StringBuffer01 { public static void main(String[] args) { String str = "hello"; StringBuffer sb1 = new StringBuffer(str); StringBuffer sb2 = new StringBuffer(); sb2.append(str); } }
|
转为StringBuffer
1 2 3 4 5 6 7
| public class StringBuffer01 { public static void main(String[] args) { StringBuffer sb = new StringBuffer("Hello"); String str1 = sb.toString(); String str2 = new String(sb); } }
|
StringBuffer常用方法
append
在末尾添加字符
1 2 3 4 5 6 7
| public class StringBuffer01 { public static void main(String[] args) { StringBuffer sb = new StringBuffer("Hello"); sb.append(" World!!"); System.out.println(sb); } }
|
delete
删除 [1,3)的内容
1 2 3 4 5 6 7
| public class StringBuffer01 { public static void main(String[] args) { StringBuffer sb = new StringBuffer("Hello"); sb.delete(1, 3); System.out.println(sb.toString()); } }
|
replace
替换,有三个参数,从 [1,3)的内容用参数 3 替换
1 2 3 4 5 6 7
| public class StringBuffer01 { public static void main(String[] args) { StringBuffer sb = new StringBuffer("Hello"); sb.replace(1, 3, "世界"); System.out.println(sb.toString()); } }
|
indexOf
返回查找内容的索引(第一个)传入字符串
1 2 3 4 5 6
| public class StringBuffer01 { public static void main(String[] args) { StringBuffer sb = new StringBuffer("Hello"); System.out.println(sb.indexOf("l")); } }
|
insert
在(第一个参数的位置)插入内容
1 2 3 4 5 6 7
| public class StringBuffer01 { public static void main(String[] args) { StringBuffer sb = new StringBuffer("Hello"); sb.insert(1, "插入"); System.out.println(sb); } }
|
length
返回长度
1 2 3 4 5 6
| public class StringBuffer01 { public static void main(String[] args) { StringBuffer sb = new StringBuffer("Hello"); System.out.println(sb.length()); } }
|
常见的例题
使用append传入null字符串
当为null的时候返回appendNull,而返回的值是一个null字符串
1 2 3 4 5 6 7 8 9
| public class StringBuffer01 { public static void main(String[] args) { StringBuffer sb = new StringBuffer(); String str = null; sb.append(str); System.out.println(sb.length()); System.out.println(sb.toString()); } }
|
1 2 3 4 5 6 7 8 9
| public AbstractStringBuilder append(String str) { if (str == null) return appendNull(); int len = str.length(); ensureCapacityInternal(count + len); str.getChars(0, len, value, count); count += len; return this; }
|
1 2 3 4 5 6 7 8 9 10 11
| private AbstractStringBuilder appendNull() { int c = count; ensureCapacityInternal(c + 4); final char[] value = this.value; value[c++] = 'n'; value[c++] = 'u'; value[c++] = 'l'; value[c++] = 'l'; count = c; return this; }
|
第二种情况:使用构造器传入null
1 2 3 4 5 6
| public class StringBuffer01 { public static void main(String[] args) { String str = null; StringBuffer sb = new StringBuffer(str); } }
|
1 2 3 4
| public StringBuffer(String str) { super(str.length() + 16); append(str); }
|
一个在价格中增添,的代码示例
1 2 3 4 5 6 7 8 9 10 11 12
| public class StringBuffer01 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String price = sc.nextLine(); StringBuffer sb = new StringBuffer(price); int index = sb.indexOf("."); for(int i = index - 3; i > 0; i -= 3) { sb.insert(i, ","); } System.out.println(sb); } }
|
StringBuilder
定义
1 2 3 4
| public final class StringBuilder extends AbstractStringBuilder implements Serializable, CharSequence {
|
是一个可变的字符序列,提供与StringBuffer兼容的API,但是不保证线程安全,被设计为StringBuffer的简易替换,用在字符串缓冲区被单个线程使用的时候
如果可能优先使用StringBuilder,因为它的效率大多都要比StringBuffer快
在StringBuilder上的主要操作时append和insert方法,可以重载这些方法用以接收任意类型的数据
StringBuffer继承了AbstractStringBuilder类,可串行化,可以保存在文件,是一个final类型,不可被继承
1 2 3
| abstract class AbstractStringBuilder implements Appendable, CharSequence {
char[] value;
|
字符存放在堆中
StringBuilder的方法没有作互斥的处理,没有synchronization关键字,只能在单线程中使用
String三者比较
1.StringBuilder和StringBuffer类似,均代表可变字符序列,方法一致
2.String是不可变字符序列,效率低,但是复用率高
3.StringBuffer是可变字符序列,效率较高(增删),线程安全
4.StringBuilder是可变字符序列,效率最高,线程不安全
课后练习
String str = new String(“hello”) + new String(“word”)过程中产生了几个对象
在Java中,当你使用+
运算符进行字符串拼接时,编译器会自动进行优化,底层实际上是使用StringBuilder
来实现的。这是出于性能和内存效率的考虑。
1
| String str = new String("hello") + new String("word");
|
编译器会将其转换为类似以下的字节码:
1 2 3 4
| StringBuilder sb = new StringBuilder(); sb.append(new String("hello")); sb.append(new String("word")); String str = sb.toString();
|
1.反转字符串(将指定的部分反转)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class Homework { public static void main(String[] args) { String str = new String("HelloWorld"); str = reverse(str, 0, str.length() - 1); System.out.println(str.toString()); }
public static String reverse(String str, int start, int end) { char[] arr = str.toCharArray(); for (int i = start, j = end; i < j; i++, j--) { char temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } return new String(arr); } }
|
2.判断账号密码是否正确
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class Homework { public static void main(String[] args) { String input = new Scanner(System.in).nextLine(); String[] strArray = input.split(","); if(strArray[0].length() == 2 || strArray[0] .length() == 3 || strArray[0].length() == 4) { System.out.println("用户名正确"); } if(strArray[1].length() == 6 && isDigital(strArray[1])) { System.out.println("密码正确"); } } public static boolean isDigital(String str) { char[] chars = str.toCharArray(); for (int i = 0; i < chars.length; i++) { if (!Character.isDigit(chars[i])) { return false; } } return true; } }
|