Java 常用类及常用方法
介绍jdk
中的常用的类中常用的方法 , 包括:
- String
- StringBuffer
- 基础类型对应的包装类
- 日期相关类
- 数字相关类
- Random 随机数
- Enum 枚举类
String
类
String
类不能继承,因为它是使用 final 修饰的
public final class String ...
String
表面上是一个字符串,实际上底层是用一个字符数组存的;String
类是不可变类,也就是说String
对象声明后,将不可修改
/** The value is used for character storage. */
private final char value[];
// 这个字符数组还是用 final 关键字修饰的,也是为什么String创建之后不可修改的原因
Java.lang.String; 是字符串类型
-
字符串一旦创建,不可以再改变
- 例如 “abc” 字符串对象一旦创建,就不能改变为 “abcd”
-
由于在程序中字符串经常出现,所以为了提升字符串的访问效率,在程序中使用了**“缓存”**技术。即在Java中使用 **“ ”**括起来的字符串都会在 字符串常量池 中创建一份
-
字符串常量池在JVM 的方法区内存中存取
在程序执行过程中,如果程序中用到某一个字符串,例如 “abc”,那么程序会首先在 字符串常量池 中去搜索这个字符串。如果没有找到则在字符串常量池中新建一个 “abc” 字符串;如果找到了就直接拿来用。(字符串常量池是一个缓存区,是为了提高字符串的访问效率)
public class Test01 { public static void main(String[] args) { String s1 = "abc"; String s2 = "abc"; // == 比较的是两个引用指向的内存空间 System.out.println(s1 == s2); // 输出啥? // true String s3 = new String("bcd"); // 存储在栈空间 String s4 = new String("bcd"); System.out.println(s3 == s4);// 输出啥? // false System.out.println(s3.equals(s4)); // String 类中的 equals方法比较的是字符串的值 // 输出 true // 以下程序执行会在字符串常量池中创建 3 个 字符串常量 // "aaa", "bbb", "aaabbb" // 所以在涉及到频繁的字符串拼接的程序中,不推荐使用 直接字符串相+ String s5 = "aaa"; String s6 = "bbb"; String s7 = s5 + s6; } }
-
-
分析以下程序创建字符串对象的区别
public class Test02 { public static void main(String[] args) { String s1 = "abc"; String s2 = new String("abc"); } }
-
String s1 = “abc”; 只会在方法区中的 “字符串常量池” 中创建一个 “abc” 字符串对象
-
String s2 = new String(“bac”); 会在字符串常量池中创建一个 “bac” 字符串对象,并且会在 堆内存 中再创建一个字符串对象
第二种方式比较浪费内存,常用的是第一种方式
-
判断以下程序中创建了几个字符串对象
public class Test03 { public static void main(String[] args) { String s1 = new String("abc"); String s2 = new String("abc"); } }
- 创建了 3 个字符串对象
- 堆内存中创建 2 个
- 方法区内存中的 字符串常量池 中创建了 1 个
- 注意:
- 堆内存区中是运行时分配的
- 方法区内存区中的 字符串常量池 是 编译时 分配的
- 创建了 3 个字符串对象
-
使用String类型的字符串时请注意不要进行字符串的频繁拼接
- 字符串一旦创建就不可改变,频繁拼接会在方法区内存的 字符串常量池 中创建大量的字符串对象,给垃圾回收带来困难。
关于字符串中的常用方法:
-
常用的构造方法
public class Test04 { public static void main(String[] args) { // 1 String s1 = "abc"; // 2 String s2 = new String("abc"); // 3 byte[] bytes = {97, 98, 99, 100}; String s3 = new String(bytes); // abcd System.out.println(s3); // 4 String s4 = new String(bytes, 1, 3); // bcd System.out.println(s4); // 5 char[] chars = {'a', 'b','c', 'd', 'e'}; String s5 = new String(chars);// abcde System.out.println(s5); // 6 String s6 = new String(chars, 2, 2);// cd System.out.println(s6); } }
-
常用的方法
package com.test.classandmethod; public class Test05 { public static void main(String[] args) { //1. char charAt(int index) char c1 = "abcedfa".charAt(3); System.out.println(c1); // e //2. boolean endsWith(String suffix) System.out.println("HelloWorld.java".endsWith(".java")); // true //3. boolean equals(Object anObject) System.out.println("hello".equals(new String("hello"))); // true //4. boolean equalsIgnoreCase(String anotherString) System.out.println("hello".equalsIgnoreCase("Hello")); //5. byte[] getBytes() byte[] res = "hello".getBytes(); for(int i=0; i<res.length; i++) { System.out.print(res[i]+" "); // 104 101 108 108 111 } System.out.println(); //6. int indexOf(String str) int index = "jdhfadfa".indexOf("a"); System.out.println(index); // 4 //7. int indexOf(String str, int fromIndex) index = "jkdhkajlf".indexOf("j", 2); System.out.println(index); // 6 //8. int lastIndexOf(String str) index = "jdhfakljdhfap[qijkmdnv;kajkha".lastIndexOf("f"); System.out.println(index); // 10 //9. int lastIndexOf(String str, int fromIndex) // 从开始位置往前找 index = "jdhfakljdhfap[qijkmdnv;kajka".lastIndexOf("h", 6); System.out.println(index); // 2 //10. int length() System.out.println("hdgahdg".length());// 7 //11. String replaceAll(String regex, String replacement) String resS = "jkhaflkjhfdlakjdfha".replaceAll("d", "D"); System.out.println(resS);//jkhaflkjhfDlakjDfha //12. String[] split(String regex) String[] s1 = "jdhaflkjdhl,fmakdjfa.mafsdkfjak.sajdfhal.sdflajdfuq".split("f"); System.out.println(s1.length); for(int i=0; i<s1.length; i++) { System.out.println(s1[i]); } //13. boolean startsWith(String prefix) System.out.println("aafdsfads".startsWith("aa"));// true //14. String substring(int beginIndex); System.out.println("dhjfajdfha".substring(2)); // jfajdfha //15. String substring(int beginIndex, int endIndex) System.out.println("jahdjfa".substring(2, 5));//hdj //16. char[] toCharArray() char[] ch1 = "dkjhfaljkd".toCharArray(); for (int i = 0; i < ch1.length; i++) { System.out.print(ch1[i] + " "); //d k j h f a l j k d } System.out.println(); //17. String toLowerCase() System.out.println("JHDGFADF".toLowerCase()); //jhdgfadf System.out.println("jhdgfadf".toUpperCase()); //JHDGFADF //18. String trim() System.out.println(" ajdhflaj dhfaljkd dfhal ".trim()); //ajdhflaj dhfaljkd dfhal //19. static String valueOf(...) System.out.println(String.valueOf(true)); // true Object obj = null; System.out.println(obj); // 不会报错 相当于调用了String.valueOf(obj) System.out.println(obj.toString()); // 空指针异常 } }
-
“正则表达式”
正则表达式是一种字符模型,专门做字符串格式匹配的。正则表达式是通用的。
-
例如:
"^a{2}$" // 表示 2 个 a 字符, 等同于 "aa" String 类中有一个matches方法: public boolean matches(String regex); 用于判断正则表达式是否匹配给定的字符串;
-
一些表示:
\d 数字 \D 非数字 \w 英文字母 \W 非英文字母
public class Test06 { public static void main(String[] args) { String s1 = "jkdafa23j4ddeq32941aiuhdef89qy"; // 将 dd 替换为 中 System.out.println(s1.replaceAll("dd", "中")); // 将 dd 替换为 中 System.out.println(s1.replaceAll("d{2}", "中")); //将所有的 数字 替换为 中 System.out.println(s1.replaceAll("\\d", "中")); //将所有的 非数字 替换为 中 System.out.println(s1.replaceAll("\\D", "中")); System.out.println("aa".matches("^a{2}$")); // true System.out.println("ab".matches("^a{2}$")); // false } }
-
-
StringBuffer
和StringBuilder
java.lang.StringBuffer java.lang.StringBuilder
-
StringBuffer
和StringBuilder
是什么?是一个字符串缓冲区
-
工作原理
预先再内存中申请一块内存,以容纳字符序列。如果预留的空间不够用,则进行自动扩容,以容纳更所字符序列
-
和
String
的最大区别- String 是不可变的字符序列,存储在方法区的字符串常量池中
- StringBuffer和StringBuilder底层是一个char数组,但是这个 char 数组是可变的,并且可以自动扩容
-
StringBuffer 和 StringBuilder 的默认初始化容量是 16
-
如何优化 StringBuffer 和 StringBuilder 呢?
最好在创建 StringBuffer 和 StringBuilder 的时候预测他们存储的字符数量,然后在创建 StringBuffer 和 创建 StringBuilder 的时候采用指定初始化容量的方法创建StringBuffer/StringBuilder, 从而实现减少底层数组的拷贝,提高效率。
-
在做字符串频繁拼接的时候,建议使用 StringBuffer 和 StringBuilder
public class Test07 { public static void main(String[] args) { StringBuffer sb = new StringBuffer(20); String[] s = {"运动","休闲","娱乐","工作"}; for(int i=0; i<s.length; i++) { if(i == s.length-1) { sb.append(s[i]); }else { sb.append(s[i]); sb.append(","); } } System.out.println(sb); } }
-
Stringbuffer 和 StringBuilder 之间的区别:
- StringBuffer是线程安全
- 在多线程环境下使用不会出现问题
- StringBuilder 是非线程安全的
- 在多线程环境中使用可能会出现问题
- StringBuffer是线程安全
-
基本数据类行对应的包装类型
基本数据类型 | 包装类型 |
---|---|
byte | java.lang.Byte; |
short | java.lang.Short; |
int | java.lang.Integer; |
long | java.lang.Long; |
float | java.lang.Float; |
double | java.lang.Double; |
boolean | java.lang.Boolean; |
char | java.lang.Character; |
-
已经有基本数据类型了,为什么还要提供包装类?
为了方便
public class Test08 { public static void main(String[] args) { // 基本数据类型 byte b = 10; // 引用数据类型 Byte b1 = new Byte(b); m1(b1); // 10 Byte类已经将Object类中的 toString类重写 // 备注: 其实可以直接传进去 10, 涉及到自动装箱, 自动拆箱 } // 需求: 规定m1方法可以接收任何一种数据类型 // m1方法如果想接收byte类型的数据的时候,可以先将byte类型包装成 java.lang.Byte; 再传递参数 private static void m1(Object obj) { System.out.println(obj); } }
-
包装类的继承结构图
-
常用的包装类及常用的方法 ---- 以
java.lang.Integer
为例:-
构造方法
public class Test09 { public static void main(String[] args) { // 获取 integer 的最大值最小值 System.out.println(Integer.MAX_VALUE); System.out.println(Integer.MIN_VALUE); // 获取 Byte的最大值最小值 System.out.println(Byte.MAX_VALUE); System.out.println(Byte.MIN_VALUE); // 创建Integer类型的对象 Integer i1 = new Integer(11); // int --> Integer Integer i2 = new Integer("123"); // String ---> Integer System.out.println(i1); System.out.println(i2); // 一下程序编译可以通过,但是运行的时候会报异常 // 虽然可以将字符串转换成 Integer 类型,但是该字符串也应该是 "数字字符串" // Integer i3 = new Integer("abc");//java.lang.NumberFormatException } }
-
常用方法
-
integer 常用方法
public class Test10 { public static void main(String[] args) { // intValue, byteValue, floatValue, doubleValue, longValue // int --> Integer Integer i1 = new Integer(10); // String --> Integer Integer i3 = new Integer("132"); // Integer --> int // 引用类型 --> 基本类型 int i2 = i1.intValue(); System.out.println(i2+1); // 11 // 重要:static int parseInt(String s) // String --> int int i4 = Integer.parseInt("4321");// 里面的字符串必须是“数字字符串” System.out.println(i4+1);//4322 // 重要: static double parseDouble(String s) // String --> double double d1 = Double.parseDouble("3.14"); System.out.println(d1);//3.14 // static String toBinaryString(int i) // static String toHexString(int i) // static String toOctalString(int i); int i5 = 324; String s1 = Integer.toBinaryString(i5);//101000100 System.out.println(s1); String s2 = Integer.toHexString(i5);//144 System.out.println(s2); String s3 = Integer.toOctalString(i5);//504 System.out.println(s3); } }
-
三种类型相互转换
/** * 三种类型相互转换 * Integer * String * int * */ public class Test11 { public static void main(String[] args) { // 1. int --> Integer Integer i1 = Integer.valueOf(10); // 2. Integer --> int int i2 = i1.intValue(); // 3. String --> Integer Integer i3 = Integer.valueOf("123"); // 4. Integer --> String String s1 = i3.toString(); // 5. String --> int int i4 = Integer.parseInt("123"); // 6. int --> String String s2 = 12 + ""; } }
-
-
-
自动装箱和自动拆箱
-
自动装箱 auto_boxing
-
自动拆箱 auto_unboxing
/** * 自动装箱 * auto_boxing * 自动拆箱 * auto_unboxing * */ public class Test12 { public static void main(String[] args) { //1. // int --> Integer Integer i1 = new Integer(10); // 装箱 // Integer --> int int i2 = i1.intValue(); // 拆箱 //2. // int --> Integer Integer i3 = 10; // 自动装箱 // Integer --> int int i4 = i3; // 自动拆箱 m2(10, 5); // 自动装箱 } public static Integer m2(Integer i1, Integer i2) { return i1 - i2; // 存在自动拆箱,自动装箱 } }
-
深入自动装箱,自动拆箱
-
自动装箱 和 自动拆箱 是 程序编译阶段的概念,与程序运行无关。
-
自动装箱 和 自动拆箱 的主要目的是方便程序员的编码
-
整型常量池:
-
像方法区中的“字符串常量池”一样,java为**[-128, 127]之间的整数在方法区内存中建立了一个“整型常量池“**
-
该整型常量池只存储【-128, 127】之间的数,每个数都对应放在方法区内存空间
Integer i7 = 127;
这行代码就会直接从方法区整型常量池中寻找 127 存储的内存地址,直接给 i7;不会在堆中创建对象
-
整型常量池中的数据 在 Integer 类加载后就创建了
-
public class Test13 { public static void main(String[] args) { Integer i1 = new Integer(10);// 会在堆中创建对象 Integer i2 = new Integer(10); System.out.println(i1 == i2);// false 这里不会出现自动拆箱 // 比较两个Integer类型的数据是否相等,不能用 “==” // Integer 已经重写了 Object中的 equals 方法 System.out.println(i1.equals(i2)); // true // 重点 Integer i3 = 128; Integer i4 = 128; //上面两行代码等价于 Integer i5 = new Integer(128); Integer i6 = new Integer(128);// 发生了自动装箱 System.out.println(i3 == i4); // false // 注意以下代码(面试常考) Integer i7 = 127; // 不会在堆中创建对象,会直接从整型常量池中拿 Integer i8 = 127; // 不会在堆中创建对象,会直接从整型常量池中拿 System.out.println(i7 == i8);// true Integer i9 = -128; Integer i10 = -128; System.out.println(i9 == i10);// true Integer i11 = -129; Integer i12 = -129; System.out.println(i11 == i12); // false // 为什么会出现这种情况呢? // 如果数据在 [-128, 127] 之间,java中引入了一个"整型常量池"(在方法区内存中) // 该整型常量池只存储 [-128, 127]之间的数据(在类加载后就会创建,对应代码放在静态代码区) } }
-
-
日期类型
-
获取毫秒数
/** * 获取自 1970年1月1日0时0分0秒000毫秒到当前的毫秒数 * 1000 毫秒 = 1 秒 * java.lang * System Class * currentTimeMillis() */ public class Test14 { public static void main(String[] args) { // static long currentTimeMillis() long now = System.currentTimeMillis(); System.out.println(now); // 1583735040606 } }
-
日期格式化
import java.util.Date; import java.text.SimpleDateFormat; public class Test15 { public static void main(String[] args) { // 获取系统当前的时间 Date now = new Date(); System.out.println(now);// Mon Mar 09 14:47:44 CST 2020 // 如何定制日期的输出格式呢? // 引入格式化日期 // java.util.Date --> String // java.text.SimpleDateFormat SimpleDateFormat sdf = new SimpleDateFormat(); String sdfNow = sdf.format(now); System.out.println(sdfNow); // 20-3-9 下午2:55 sdf = new SimpleDateFormat("yyyy-MM-dd:HH-mm-ss-SSS"); sdfNow = sdf.format(now); System.out.println(sdfNow);// 2020-03-09:14-56-54-987 sdf = new SimpleDateFormat("yyyy年MM月dd日:HH时mm分ss秒SSS毫秒"); sdfNow = sdf.format(now); System.out.println(sdfNow);// 2020年03月09日:14时57分44秒278毫秒 } }
-
常用的日期格式
日期格式:
y 年
M 月
d 日
H 时
m 分
s 秒
S 毫秒
-
获取特定的日期
- 上面获取的是系统当前的日期
import java.util.Date; import java.text.ParseException;// 直接继承 Exception类,是编译型异常 import java.text.SimpleDateFormat; public class test16 { public static void main(String[] args) throws ParseException { // 获取特定时刻的日期 String strTime = "2008年8月8日 08:08:08 888"; // 将String类型的日期转换成日期类型Date的日期 // String --> Date //1. 创建日期格式化对象 SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss SSS"); //格式不能随意,应该和上面的字符串格式相同 //2. 将字符串转换成日期类型 Date date = sdf.parse(strTime);// 需要处理编译型异常 System.out.println(date);// Fri Aug 08 08:08:08 CST 2008 } }
-
获取当前时间的前10分钟的时间
import java.text.SimpleDateFormat; import java.util.Date; /* Date date = new Date();// 获取系统当前时间 Date date = new Date(long date); date - the milliseconds since January 1, 1970, 00:00:00 GMT. */ public class Test17 { public static void main(String[] args) { Date t1 = new Date(1000); // Date --> String SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); String s1 = sdf.format(t1); // 在北京东八区,所以是8点 System.out.println(s1); //1970-01-01 08:00:01 000 // 获取当前系统时间的前10分钟的时间 // 2020-03-09 16:01:38 175 // 2020-03-09 16:11:38 175 Date t2 = new Date(System.currentTimeMillis()- 1000*60*10); System.out.println(sdf.format(t2)); System.out.println(sdf.format(new Date())); } }
-
-
java.util.Calendar
日历
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; /** * 日历 * java.util.Calendar * */ public class Test18 { public static void main(String[] args) throws ParseException { // 获取系统的当前日历 // static Calendar getInstance() // Gets a calendar using the default time zone and locale. Calendar c = Calendar.getInstance(); // 查看当前日历的星期几 // int get(int field) int i = c.get(Calendar.DAY_OF_WEEK);// 中国人的星期日,外国人看作第一天 System.out.println(i);// 2 // 查看当前日历的day i = c.get(Calendar.DAY_OF_MONTH); System.out.println(i);// 9 // 获取 2008年8月8日是星期几 // void setTime(Date date) // Sets this Calendar's time with the given Date. // 1. 获取2008年8月8日的日期 String-->Date String str = "2008年08月08日"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); Date date = sdf.parse(str); // 2. 创建该日期对应的日历 c.setTime(date); // 3. 获取星期几 System.out.println(c.get(Calendar.DAY_OF_WEEK));//6 } }
数字类
-
关于数字格式化
java.text.DecimalFormat
数字格式元素:
# 任意数字 , 千分位 . 小数点 0 不够补零
/** * 数字格式化 */ import java.text.DecimalFormat; public class Test19 { public static void main(String[] args) { // 1. 创建数字格式化对象, 加入千分位 DecimalFormat df = new DecimalFormat("###,###");// 1,234,567 // 2. 开始格式化 // Number --> String System.out.println(df.format(1234567)); // 加入千分位,保留两位小数 df = new DecimalFormat("###,###.##"); System.out.println(df.format(123456.234));// 123,456.23 // 加入千分位,保留4位小数,不够补零 df = new DecimalFormat("###,###.0000"); System.out.println(df.format(1233432.23));// 1,233,432.2300 } }
-
java.math.bigDecimal;
-
该类型的数据精确度极高,适合做财务软件
-
double 类型的精度对于财务处理来说太低
import java.math.BigDecimal; public class Test20 { public static void main(String[] args) { // 创建大数据 BigDecimal v1 = new BigDecimal(10); BigDecimal v2 = new BigDecimal(20); //做加法运算 // v1+v2 // 错误,两个引用类型不能做加法运算 BigDecimal v3 = v1.add(v2); System.out.println(v3); // 30 } }
-
随机数
Random 位于 java.util 包下,可以产生随机数
import java.util.Random;
public class Test21 {
public static void main(String[] args) {
// 创建一个新的随机数生成器
Random random = new Random();
// 生成 int 类型的随机数
int i = random.nextInt(101); //生成[0,101)之间的随机数
System.out.println(i);
double d = random.nextDouble();
System.out.println(d);
}
}
枚举类型: Enum
// 枚举类型
public class Test22 {
public static void main(String[] args) {
int a = 10;
int b = 0;
Result resValue = m1(a, b);
if(Result.SUCCESS == resValue) {
System.out.println("成功");
}else {
System.out.println("失败");
}
}
// 实现两个数相乘,如果成功,返回0, 如果失败,返回1
private static Result m1(int a, int b) {
try {
int res = a/b;
return Result.SUCCESS;
} catch (Exception e) {
return Result.FAIL;
}
}
}
// 定义枚举类型
enum Result{
// 枚举类型中的成员建议大写
SUCCESS,
FAIL
}