赞
踩
Number 类是抽象类,因此它的抽象方法,所有子类都需要提供实现。Number 类提供了抽象方法:intValue()、longValue()、floatValue()、doubleValue(),意味着所有的“数字型”包装类都可以互相转型。
【示例】初识包装类
public class WrapperClassTest {
public static void main(String[ ] args) {
Integer i = new Integer(10); //从 java9 开始被废弃
Integer j = Integer.valueOf(50); //官方推荐
}
}
示例内存分析如图所示:
自动装箱(autoboxing)和拆箱(unboxing):将基本数据类型和包装类自动转换。
【示例】自动装箱
Integer i = 100;//自动装箱
//相当于编译器自动为您作以下的语法编译:
Integer i = Integer.valueOf(100);//调用的是 valueOf(100),而不是 new Integer(100)
【示例】自动拆箱
Integer i = 100;
int j = i;//自动拆箱
//相当于编译器自动为您作以下的语法编译:
int j = i.intValue();
整型、char类型所对应的包装类,在自动装箱时,对于-128~127之间的值会进行缓存处理,其目的是提高效率。
缓存原理为:如果数据在-128~127这个区间,那么在类加载时就已经为该区间的每个数值创建了对象,并将这256个对象存放到一个名为cache的数组中。每当自动装箱过程发生时(或者手动调用valueOf()时),就会先判断数据是否在该区间,如果在则直接获取数组中对应的包装类对象的引用,如果不在该区间,则会通过new调用包装类的构造方法来创建对象。
【示例】Integer 类相关源码
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
【示例】IntegerCache 类相关源码
private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { // If the property cannot be parsed into an int, ignore it. } } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); // range [-128, 127] must be interned (JLS7 5.1.7) assert IntegerCache.high >= 127; } private IntegerCache() {} }
由上面的源码我们可以看到,静态代码块的目的就是初始化数组cache的,这个过程会在类加载时完成。
总结
- 自动装箱调用的是 valueOf()方法,而不是 new Integer()方法。
- 自动拆箱调用的 xxxValue()方法。
- 包装类在自动装箱时为了提高效率,对于-128~127 之间的值会进行缓存处理。超过范围后,对象之间不能再使用==进行数值的比较,而是使用 equals 方法。
String 类代表不可变的字符序列
StringBuilder 类和 StringBuffer 类代表可变字符序列。
String 类对象代表不可变的 Unicode 字符序列,因此我们可以将 String 对象称为“不可变对象”。 那什么叫做“不可变对象”呢?指的是对象内部的成员变量的值无法再改变。
我们打开 String 类的源码,如图所示:
我们发现字符串内容全部存储到 value[ ]数组中,而变量 value 是 final 类型的,也就是常量(即只能被赋值一次)。 这就是“不可变对象”的典型定义方式。
在遇到字符串常量之间的拼接时,编译器会做出优化,即在编译期间就会完成字符串的拼接。因此,在使用==进行 String 对象之间的比较时,我们要特别注意,如示例所示。
【示例】字符串常量拼接时的优化
public class TestString2 {
public static void main(String[ ] args) {
//编译器做了优化,直接在编译的时候将字符串进行拼接
String str1 = "hello" + " java";//相当于 str1 = "hello java";
String str2 = "hellojava";
System.out.println(str1 == str2);//true
String str3 = "hello";
String str4 = " java";
//编译的时候不知道变量中存储的是什么,所以没办法在编译的时候优化
String str5 = str3 + str4;
System.out.println(str2 == str5);//false
}
}
StringBuffer 和 StringBuilder 都是可变的字符序列。
【示例】StringBuffer/StringBuilder 基本用法
public class TestStringBufferAndBuilder{ public static void main(String[ ] args) { /**StringBuilder*/ StringBuilder sb = new StringBuilder(); for (int i = 0; i < 7; i++) { sb.append((char) ('a' + i));//追加单个字符 } System.out.println(sb.toString());//转换成 String 输出 sb.append(", I can sing my abc!");//追加字符串 System.out.println(sb.toString()); /**StringBuffer,下面的方法同样适用 StringBuilder*/ StringBuffer sb2 = new StringBuffer("Java"); sb2.insert(0, "爱").insert(0, "我");//插入字符串 System.out.println(sb2); sb2.delete(0, 2);//删除子字符串 System.out.println(sb2); sb2.deleteCharAt(0).deleteCharAt(0);//删除某个字符 System.out.println(sb2.charAt(0));//获取某个字符 System.out.println(sb2.reverse());//字符串逆序 } }
String 一经初始化后,就不会再改变其内容了。对 String 字符串的操作实际上是对其副本(原始拷贝)的操作,原来的字符串一点都没有改变。比如:
String s ="a"; 创建了一个字符串
s = s+“b”; 实际上原来的"a"字符串对象已经丢弃了,现在又产生了另一个字符串s+“b”(也就是"ab")。 如果多次执行这些改变串内容的操作,会导致大量副本字符串对象存留在内存中,降低效率。如果这样的操作放到循环中,会极大影响程序的时间和空间性能,甚至会造成服务器的崩溃。
相反,StringBuilder 和 StringBuffer 类是对原字符串本身操作的,可以对字符串进行修改而不产生副本拷贝或者产生少量的副本。因此可以在循环中使用。
【示例】String 和 StringBuilder 在字符串频繁修改时的效率测试
public class Test { public static void main(String[ ] args) { /**使用 String 进行字符串的拼接*/ String str8 = ""; long num1 = Runtime.getRuntime().freeMemory();//获取系统剩余内存空间 long time1 = System.currentTimeMillis();//获取系统的当前时间 for (int i = 0; i < 5000; i++) { str8 = str8 + i;//相当于产生了 5000 个对象 } long num2 = Runtime.getRuntime().freeMemory(); long time2 = System.currentTimeMillis(); System.out.println("String 占用内存 : " + (num1 - num2)); System.out.println("String 占用时间 : " + (time2 - time1)); /**使用 StringBuilder 进行字符串的拼接*/ StringBuilder sb1 = new StringBuilder(""); long num3 = Runtime.getRuntime().freeMemory(); long time3 = System.currentTimeMillis(); for (int i = 0; i < 5000; i++) { sb1.append(i); } long num4 = Runtime.getRuntime().freeMemory(); long time4 = System.currentTimeMillis(); System.out.println("StringBuilder 占用内存 : " + (num3 - num4)); System.out.println("StringBuilder 占用时间 : " + (time4 - time3)); } }
执行结果如图所示:
“时间如流水,一去不复返”,时间是一维的。所以,我们需要一把刻度尺来表达和度量时间。在计算机世界,我们把 1970 年 1 月 1 日 00:00:00 定为基准时间,每个度量单位是毫秒(1 秒的千分之一),如图所示。
我们用 long 类型的变量来表示时间,从基准时间前后几亿年都能表示。
这个“时刻数值”是所有时间类的核心值,年月日都是根据这个“数值”计算出来的。
【示例】Date 类的使用
System.currentTimeMillis():时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总毫秒数
long nowNum = System.currentTimeMillis(); //当前时刻对应的毫秒数
Date d = new Date(); //当前时刻的对象
System.out.println(d.getTime()); //返回时间对应的毫秒数
Date d2 = new Date(1000L * 3600 * 24 * 365 * 150); //距离 1970年 150 年
System.out.println(d2);
DateFormat 类的作用
把时间对象转化成指定格式的字符串。反之,把指定格式的字符串转化成时间对象。
DateFormat 是一个抽象类,一般使用它的的子类 SimpleDateFormat 类来实现。
【示例】DateFormat 类和 SimpleDateFormat 类的使用
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class TestDateFormat { public static void main(String[ ] args) throws ParseException { // new 出 SimpleDateFormat 对象 SimpleDateFormat s1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); SimpleDateFormat s2 = new SimpleDateFormat("yyyy-MM-dd"); // 将时间对象转换成字符串 String daytime = s1.format(new Date()); System.out.println(daytime); System.out.println(s2.format(new Date())); System.out.println(new SimpleDateFormat("hh:mm:ss").format(new Date())); // 将符合指定格式的字符串转成成时间对象.字符串格式需要和指定格式一致。 String time = "2049-10-1"; Date date = s2.parse(time); System.out.println("date1: " + date); time = "2049-10-1 20:15:30"; date = s1.parse(time); System.out.println("date2: " + date); } }
字母 | 日期或时间元素 | 表示 | 示例 |
---|---|---|---|
G | Era 标志符 | Text | AD |
y | 年 | Year | 1996; 96 |
M | 年中的月份 | Month | July; Jul; 07 |
w | 年中的周数 | Number | 27 |
W | 月份中的周数 | Number | 2 |
D | 年中的天数 | Number | 189 |
d | 月份中的天数 | Number | 10 |
F | 月份中的星期 | Number | 2 |
E | 星期中的天数 | Text | Tuesday; Tue |
a | Am/pm 标记 | Text | PM |
H | 一天中的小时数(0-23) | Number | 0 |
k | 一天中的小时数(1-24) | Number | 24 |
K | am/pm | 中的小时数(0-11) | Number |
h | am/pm 中的小时数(1-12) | Number | 12 |
m | 小时中的分钟数 | Number | 30 |
s | 分钟中的秒数 | Number | 55 |
S | 毫秒数 | Number | 978 |
z | 时区 | General time zone | Pacific Standard Time; PST; GMT-08:00 |
Z | 时区 | RFC 822 time zone | 0800 |
【示例】获取今天时本年度第几天
import java.text.SimpleDateFormat;
import java.util.Date;
public class TestDateFormat2 {
public static void main(String[ ] args) {
SimpleDateFormat s1 = new SimpleDateFormat("D");
String daytime = s1.format(new Date());
System.out.println(daytime);
}
}
Calendar 类是一个抽象类,为我们提供了关于日期计算的功能,比如:年、月、日、时、分、秒的展示和计算。
获取Calendar实例的方法
注意月份的表示,一月是 0,二月是 1,以此类推,12 月是 11。 因为大多数人习惯于使用单词而不是使用数字来表示月份,这样程序也许更易读,父类 Calendar 使用常量来表示月份:JANUARY、FEBRUARY 等等。
【示例】GregorianCalendar 类和 Calendar 类的使用
import java.util.*; public class TestCalendar { public static void main(String[ ] args) { // 得到相关日期元素 GregorianCalendar calendar = new GregorianCalendar(2049, 9, 1, 22, 10, 50); int year = calendar.get(Calendar.YEAR); // 打印:2049 int month = calendar.get(Calendar.MONTH); // 打印:9 int day = calendar.get(Calendar.DAY_OF_MONTH); // 打印:1 int day2 = calendar.get(Calendar.DATE); // 打印:1 // 日:Calendar.DATE 和 Calendar.DAY_OF_MONTH 同义 int date = calendar.get(Calendar.DAY_OF_WEEK); // 打印:1 // 星期几 这里是:1-7.周日是 1,周一是 2,。。。周六是 7 System.out.println(year); System.out.println(month); System.out.println(day); System.out.println(day2); System.out.println(date); // 设置日期 GregorianCalendar calendar2 = new GregorianCalendar(); calendar2.set(Calendar.YEAR, 2049); calendar2.set(Calendar.MONTH, Calendar.OCTOBER); // 月份数:0-11 calendar2.set(Calendar.DATE, 1); calendar2.set(Calendar.HOUR_OF_DAY, 10); calendar2.set(Calendar.MINUTE, 20); calendar2.set(Calendar.SECOND, 23); printCalendar(calendar2); // 日期计算 GregorianCalendar calendar3 = new GregorianCalendar(2049, 9, 1, 22, 10,50); calendar3.add(Calendar.MONTH, -7); // 月份减 7 calendar3.add(Calendar.DATE, 7); // 增加 7 天 printCalendar(calendar3); // 日历对象和时间对象转化 Date d = calendar3.getTime(); GregorianCalendar calendar4 = new GregorianCalendar(); calendar4.setTime(new Date()); } static void printCalendar(Calendar calendar) { int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH) + 1; int day = calendar.get(Calendar.DAY_OF_MONTH); int date = calendar.get(Calendar.DAY_OF_WEEK) - 1; // 星期几 String week = "" + ((date == 0) ? "日" : date); int hour = calendar.get(Calendar.HOUR); int minute = calendar.get(Calendar.MINUTE); int second = calendar.get(Calendar.SECOND); System.out.printf("%d 年%d 月%d 日,星期%s %d:%d:%d\n", year, month, day,week, hour, minute, second); } }
【示例】Calendar.getInstance()
@Test public void test3() throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); //产生 Calendar c = Calendar.getInstance(); //当前时间new Date() //得到field System.out.println(c.get(Calendar.YEAR)); //得到年 System.out.println(c.get(Calendar.MONTH)); //得到月 传统日期月从0开始,周从周日=1开始 System.out.println(c.get(Calendar.DAY_OF_MONTH)); System.out.println(c.get(Calendar.HOUR_OF_DAY)); //设置field c.set(Calendar.MONTH, 0); //传统日期月从0开始 System.out.println(sdf.format(c.getTime()));//得到date //减3个月 c.add(Calendar.MONTH, -3); System.out.println(sdf.format(c.getTime()));//得到date //创建1970-1-1 8:0:0.0时间 //方式1: String dateStr = "1970-01-1 08:0:0.0"; //把字符串解析成日期,string->date Date date1 = sdf.parse(dateStr); System.out.println(date1.getTime()); //方式2 Calendar c2 = Calendar.getInstance(); c2.set(1970, 0, 1,8,0,0); c2.set(Calendar.MILLISECOND, 0); System.out.println(sdf.format(c2.getTime())); //当前时间的4周后 Calendar c3 = Calendar.getInstance(); //当前时间 c3.add(Calendar.WEEK_OF_YEAR, 5); System.out.println(sdf.format(c3.getTime())); }
Java 8中引入的java.time API 已经纠正了过去的缺陷,将来很长一段时间内它都会为我们服务。
Java 8 吸收了 Joda-Time 的精华,以一个新的开始为 Java 创建优秀的 API。新的 java.time 中包含了所有关于本地日期(LocalDate)、本地时间(LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime)和持续时间(Duration)的类。历史悠久的 Date 类新增了 toInstant() 方法,用于把 Date 转换成新的表示形式。这些新增的本地化时间日期 API 大大简化了日期时间和本地化的管理。
LocalDate、 LocalTime、 LocalDateTime 类是其中较重要的几个类,它们的实例是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。
方法 | 描述 |
---|---|
now() / * now(ZoneId zone) | 静态方法, 根据当前时间创建对象/指定时区的对象 |
of() | 静态方法, 根据指定日期/时间创建对象 |
getDayOfMonth()/getDayOfYear() | 获得月份天数(1-31) /获得年份天数(1-366) |
getDayOfWeek() | 获得星期几(返回一个 DayOfWeek 枚举值) |
getMonth() | 获得月份, 返回一个 Month 枚举值 |
getMonthValue() / getYear() | 获得月份(1-12) /获得年份 |
getHour()/getMinute()/getSecond() | 获得当前对象对应的小时、 分钟、 秒 |
withDayOfMonth()/withDayOfYear()/ withMonth()/withYear() | 将月份天数、 年份天数、 月份、 年份修改为指定的值并返回新的对象 |
plusDays(), plusWeeks(), plusMonths(), plusYears(),plusHours() | 向当前对象添加几天、 几周、 几个月、 几年、 几小时 |
minusMonths() / minusWeeks()/ minusDays()/minusYears()/minusHours() | 从当前对象减去几月、 几周、 几天、 几年、 几小时 |
方法 | 描述 |
---|---|
now() | 静态方法, 返回默认UTC时区的Instant类的对象 |
ofEpochMilli(long epochMilli) | 静态方法 数之后的,Instant 返回在类的对象 1970-01-01 00:00:00基础上加上指定毫秒 |
atOffset(ZoneOffset offset) | 结合即时的偏移来创建一个 OffsetDateTime |
toEpochMilli() | 返回1970-01-01 00:00:00到当前时间的毫秒数, 即为时间戳 |
**注意:**时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总毫秒数
java.time.format.DateTimeFormatter 类:该类提供了三种格式化方法:
方 法 | 描 述 |
---|---|
ofPattern(String pattern) | 静 态 方 法 , 返 回 一 个 指 定 字 符 串 格 式 的 DateTimeFormatter |
format(TemporalAccessor t) | 格式化一个日期、 时间, 返回字符串 |
parse(CharSequence text) | 将指定格式的字符序列解析为一个日期、 时间 |
@Test public void test5() throws ParseException { //得到当前时间 //LocalDateTime:(UTC)日期时间,理解成Date + Calander //LocalDate:日期 //LocalTime:时间 LocalDateTime l1 = LocalDateTime.now(); System.out.println("l1 = " + l1); //得到field System.out.println(l1.getMonth().getValue()); //新时间api,月从1开始 System.out.println(l1.getYear()); System.out.println(l1.get(ChronoField.HOUR_OF_DAY)); //时 //设置field,支持chain方法链,设置1月1日 LocalDateTime l2 = l1.withMonth(1).withDayOfMonth(1); System.out.println(l2); //加3个月,加3周 // l2.plusMonths(3).plus(3, ChronoUnit.WEEKS) LocalDateTime l3 = l2.plusMonths(3).plusWeeks(3); System.out.println(l3); //减3月 LocalDateTime l4 = l3.minusMonths(3); System.out.println(l4); //创建1970-1-1 8:0:0.0时间 LocalDateTime l5 = LocalDateTime.of(1970, 1, 1, 0, 0, 0, 0); System.out.println(l5); //时间戳操作 Instant Instant i1 = l5.toInstant(ZoneOffset.UTC); //得到utc时间的Instant System.out.println(i1.toEpochMilli()); // ZoneOffset.getAvailableZoneIds().forEach(s -> System.out.println(s)); LocalDateTime l6 = LocalDateTime.of(1970, 1, 1, 8, 0, 0, 0); Instant i2 = l6.toInstant(ZoneOffset.ofHours(8)); //得到东8区的Instant System.out.println(i2.toEpochMilli()); //utc时间的1970.1.1.0点,北京时间的8点,是时间戳的0 //格式化 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒.SSS"); System.out.println(formatter.format(LocalDateTime.now())); // formatter.parse() //解析一个时间 }
【示例】Math 类的常用方法
public class TestMath { public static void main(String[ ] args) { //取整相关操作 System.out.println(Math.ceil(3.2)); System.out.println(Math.floor(3.2)); System.out.println(Math.round(3.2)); System.out.println(Math.round(3.8)); //绝对值、开方、a 的 b 次幂等操作 System.out.println(Math.abs(-45)); System.out.println(Math.sqrt(64)); System.out.println(Math.pow(5, 2)); System.out.println(Math.pow(2, 5)); //Math 类中常用的常量 System.out.println(Math.PI); System.out.println(Math.E); //随机数 System.out.println(Math.random());// [0,1) } }
执行结果如图所示:
public class SystemDemo1 { public static void main(String[] args) { Scanner in = new Scanner(System.in); //得到用户控制台输入 System.out.println("请输入i,输入0退出"); int i = in.nextInt(); if (i == 0) { System.exit(0); } System.out.println("i=" + i); } @Test public void test1() { Scanner in = new Scanner(System.in); //得到用户控制台输入 System.out.println("请输入i,输入0退出"); int i = in.nextInt(); if (i == 0) { System.exit(0); } System.out.println("i=" + i); } @Test public void test2() { System.out.println(System.currentTimeMillis()); } @Test public void test3() { String javaVersion = System.getProperty("java.version"); System.out.println("java的version:" + javaVersion); String javaHome = System.getProperty("java.home"); System.out.println("java的home:" + javaHome); String osName = System.getProperty("os.name"); System.out.println("os的name:" + osName); String osVersion = System.getProperty("os.version"); System.out.println("os的version:" + osVersion); String userName = System.getProperty("user.name"); System.out.println("user的name:" + userName); String userHome = System.getProperty("user.home"); System.out.println("user的home:" + userHome); String userDir = System.getProperty("user.dir"); System.out.println("user的dir:" + userDir); } }
public void addShutdownHook(Thread hook):捕获jvm退出时间
import java.util.Random; public class TestRandom { public static void main(String[ ] args) { Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { @Override public void run() { System.out.println("捕获了jvm退出--释放资源"); } })); Random rand = new Random(); //随机生成[0,1)之间的 double 类型的数据 System.out.println(rand.nextDouble()); //随机生成 int 类型允许范围之内的整型数据 System.out.println(rand.nextInt()); //随机生成[0,1)之间的 float 类型的数据 System.out.println(rand.nextFloat()); //随机生成 false 或者 true System.out.println(rand.nextBoolean()); //随机生成[0,10)之间的 int 类型的数据 System.out.print(rand.nextInt(10)); //随机生成[20,30)之间的 int 类型的数据 System.out.print(20 + rand.nextInt(10)); } }
File 类的基本用法
java.io.File 类:代表文件和目录,用于:读取文件、创建文件、删除文件、修改文件。
【示例】使用 File 类创建文件
File 类的常见构造方法:public File(String pathname)
以 pathname 为路径创建 File 对象,如果 pathname 是相对路径,则默认的当前路径在系统属性 user.dir 中存储。
import java.io.File;
public class TestFile1 {
public static void main(String[ ] args) throws Exception {
System.out.println(System.getProperty("user.dir"));
File f = new File("a.txt"); //相对路径:默认放到 user.dir 目录下面
f.createNewFile();//创建文件
File f2 = new File("d:/b.txt");//绝对路径
f2.createNewFile();
}
}
user.dir 就是本项目的目录。上面代码执行后,在本项目和 D 盘下都生成了新的文件。
1.通过 File 对象可以访问文件的属性:
2.通过 File 对象创建空文件或目录(在该对象所指的文件或目录不存在的情况下)
public class BigIntegerDemo { @Test public void test1() { System.out.println(Integer.MAX_VALUE); Integer i1 = 2147483647; // Integer i2 = 2147483648; BigInteger i3= new BigInteger("10"); System.out.println(i3); BigInteger i4 = new BigInteger("15"); BigInteger i5 = i3.add(i4); System.out.println(i5); BigInteger[] arrs = i3.divideAndRemainder(new BigInteger("3")); System.out.println(Arrays.toString(arrs)); } }
正则表达式,又称规则表达式,(Regular Expression,在代码中常简写为regex、regexp或RE),是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符"),是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式(规则)的文本。
简单来说,正则表达式就是一个很牛逼的字符串处理工具。
正则在线工具 : https://c.runoob.com/front-end/854/?optionGlobl=global
public class StringRegexDemo1 { public static void main(String[] args) { Scanner in = new Scanner(System.in); while (true) { System.out.println("请输入qq"); String s1 = in.nextLine(); //匹配s1中是否是6-12位数字 System.out.println(s1.matches("^[0-9]{6,12}$")); } } @Test public void test1() { String s = "Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的高级程序设计语言Java 可运行于多个平台,如 windows,Mac OS 及其他多种 UNIX 版本的系统"; // s = s.replaceAll("[a-zA-Z]{1,}", "hello"); s = s.replaceAll("[a-zA-Z]+", "hello"); s = s.replaceAll("\\d+", "world"); System.out.println(s); } @Test public void test2() { String s1 = "aaa,bbb,123,456,hello,word"; String[] arrs = s1.split(","); for (int i = 0; i < arrs.length; i++) { System.out.println(arrs[i]); } } @Test public void test3() { String s2 = "hello12333world4567welcome34to4beijing"; String[] arrs2 = s2.split("\\d+"); for (int i = 0; i < arrs2.length; i++) { System.out.println(arrs2[i]); } } }
pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
索引方法提供了有用的索引值,精确表明输入字符串中在哪能找到匹配:
查找方法用来检查输入字符串并返回一个布尔值,表示是否找到该模式:
替换方法是替换输入字符串里文本的方法:
public class RegexDemo1 { public static void main(String[] args) { Scanner in = new Scanner(System.in); // Pattern pattern = Pattern.compile("^[0-9]{5,12}$"); //正则的编译对象 while (true) { System.out.println("请输入qq"); String s1 = in.nextLine(); Matcher matcher = pattern.matcher(s1); System.out.println(matcher.matches()); //全部匹配 // System.out.println(s1.matches("^[0-9]{5,12}$")); } } @Test public void test1() { //正则编译对象,只匹配一次可以使用matches方法 System.out.println(Pattern.matches("^[0-9]{5,12}$", "77546313")); //正则是否全部匹配 System.out.println(Pattern.matches("^[0-9]{5,12}$", "123456")); //正则是否全部匹配 System.out.println(Pattern.matches("^[0-9]{5,12}$", "333333")); //正则是否全部匹配 Pattern pattern = Pattern.compile("^[0-9]{5,12}$"); pattern.matcher("77546313").matches(); pattern.matcher("123456").matches(); pattern.matcher("333333").matches(); } @Test public void test2() { //全部匹配 Pattern pattern = Pattern.compile("\\d{5,12}"); Matcher matcher = pattern.matcher("12345a34343434"); System.out.println(matcher.matches()); //全部匹配 } @Test public void test3() { //全部匹配 Pattern pattern = Pattern.compile("\\d{5,12}"); Matcher matcher = pattern.matcher("12345a34343434abc9878989"); while (matcher.find()) {//查找匹配,如果匹配返回ture String target = matcher.group();//得到上一次匹配的子序列 System.out.println(target + "-" + matcher.start() + "-" + matcher.end()); //start得到上一个匹配的索引开始 } } @Test public void test4() { String content = "Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的高级程序设计语言。\n" + "Java 可运行于多个平台,如 windows,Mac OS 及其他多种 UNIX 版本的系统。\n" + "本教程通过简单的实例将让大家更好的了解 Java 编程语言。\n" + "移动操作系统 Android 大部分的代码采用 Java 编程语言编程。"; Pattern pattern = Pattern.compile("([a-zA-Z]+) | (\\d+)"); Matcher matcher = pattern.matcher(content); while (matcher.find()) { String target = matcher.group(2); //0:全部的正则捕获组,1:的一个小括号的正则补货组 System.out.println(target); } } @Test public void test6() { String content = "Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的高级程序设计语言。\n" + "Java 可运行于多个平台,如 windows,Mac OS 及其他多种 UNIX 版本的系统。\n" + "本教程通过简单的实例将让大家更好的了解 Java 编程语言。\n" + "移动操作系统 Android 大部分的代码采用 Java 编程语言编程。"; //创建一个Pattern对象 Pattern pattern = Pattern.compile("Java"); //创建一个匹配对象 Matcher matcher = pattern.matcher(content); StringBuffer sb = new StringBuffer(); while (matcher.find()) { //将Java替换为java后,将最后匹配到之前的子串都添加到sb对象中 matcher.appendReplacement(sb, "java"); System.out.println("sb:" + sb); System.out.println("---------分割线-----------"); } //将最后匹配到的子串添加到sb中 matcher.appendTail(sb); System.out.println("sb: " + sb); } }
元符号-转义号\
\符号说明:在我们使用正则表达式去检索某些特殊字符的时候,需要用到转义字符,否则检测不到结果,甚至会报错。
需要用到转义符的字符有:. * + ( )$ / \ ? [ ] ^ { }
注意:在Java的正则表达式中,两个\代表其他语言中的一个\
正则表达式所支持的合法字符
字符 | 解释 |
---|---|
X | 字符x(x 可代表任何合法的字符) |
\0mnn | 八进制数 0mnn 所表示的字符 |
\xhh | 十六进制值 0xhh 所表示的字符 |
\uhhhh | 十六进制值 0xhhhh 所表示的 Unicode 字符 |
\t | 制表符(“\u0009”) |
\n | 新行(换行)符(‘\u000A’) |
\r | 回车符(‘\u000D’) |
\f | 换页符(‘\u000C’) |
\a | 报警(bell)符(‘\u0007’) |
\e | Escape 符(‘\u001B’) |
\cx | x 对应的的控制符。例如,\cM匹配 Ctrl-M。x 值必须为 A~Z 或 a~z 之一。 |
正则表达式中的特殊字符
特殊字符 | 说明 |
---|---|
$ | 匹配一行的结尾。要匹配 $ 字符本身,请使用$ |
^ | 匹配一行的开头。要匹配 ^ 字符本身,请使用^ |
() | 标记子表达式的开始和结束位置。要匹配这些字符,请使用(和) |
[] | 用于确定中括号表达式的开始和结束位置。要匹配这些字符,请使用[和] |
{} | 用于标记前面子表达式的出现频度。要匹配这些字符,请使用{和} |
* | 指定前面子表达式可以出现零次或多次。要匹配 * 字符本身,请使用* |
+ | 指定前面子表达式可以出现一次或多次。要匹配 + 字符本身,请使用+ |
? | 指定前面子表达式可以出现零次或一次。要匹配 ?字符本身,请使用? |
. | 匹配除换行符\n之外的任何单字符。要匹配.字符本身,请使用. |
\ | 用于转义下一个字符,或指定八进制、十六进制字符。如果需匹配\字符,请用\ |
| | 指定两项之间任选一项。如果要匹配丨字符本身,请使用| |
预定义字符
预定义字符 | 说明 |
---|---|
. | 可以匹配任何字符 |
\d | 匹配 0~9 的所有数字 |
\D | 匹配非数字 |
\s | 匹配所有的空白字符,包括空格、制表符、回车符、换页符、换行符等 |
\S | 匹配所有的非空白字符 |
\w | 匹配所有的单词字符,包括 0~9 所有数字、26 个英文字母和下画线_ |
\W | 匹配所有的非单词字符 |
方括号表达式
方括号表达式 说明 表示枚举 例如 [abc]表示 a、b、c 其中任意一个字符; [gz]表示 g、z 其中任意一个字符 表示范围:- 例如 [a-f]表示 a~f 范围内的任意字符; [\u0041-\u0056]表示十六进制字符 \u0041 到 \u0056 范围的字符。范围可以和枚举结合使用,如 [a-cx-z],表示 ac、xz 范围内的任意字符 表示求否:^ 例如 [^abc]表示非 a、b、c 的任意字符; [^a-f]表示不是 a~f 范围内的任意字符 表示“与”运算:&& 例如 [a-z&&[def]]是 a~z 和 [def] 的交集,表示 d、ef[a-z&&^bc]]是 a~z 范围内的所有字符,除 b 和 c 之外[ad-z] [a-z&&[m-p]]是 a~z 范围内的所有字符,除 m~p 范围之外的字符 表示“并”运算 并运算与前面的枚举类似。例如 [a-d[m-p]]表示 [a-dm-p]
补充:
Java正则表达式默认是区分字母大小写的,如要实现不区分大小写
(?i)abc表示abc都不区分大小写
a(?i)bc表示bc不区分大小写
a((?i)b)c表示只有b不区分大小写
Pattern pattern=Pattern.compile(regStr,Pattern.CASE_INSENSITIVE);
//当创建Pattern对象时,指定Pattern.CASE_INSENSITIVE,表示匹配不区分字母大小写
细节:Java匹配默认贪婪匹配,即尽可能匹配多的,比如"a{3,4}“,表示匹配aaa或者aaaa,但是优先匹配aaaa,例如原字符串中包括"aaaaaa”,匹配"a{3,4}“时,会找到"aaaa”
从正则表达式左侧开始,每出现一个左括号"("记做一个分组,分组编号从 1 开始。0 代表整个表达式。常用分组构造形式(pattern)
对于时间字符串:2017-04-25,表达式如下
(\d{4})-((\d{2})-(\d{2}))
有 4 个左括号,所以有 4 个分组:
编号 | 捕获组 | 匹配 |
---|---|---|
0 | (\d{4})-((\d{2})-(\d{2})) | 2017-04-25 |
1 | (\d{4}) | 2017 |
2 | ((\d{2})-(\d{2})) | 04-25 |
3 | (\d{2}) | 04 |
4 | (\d{2}) | 25 |
Pattern pattern=Pattern.compile("^[\u0391-\uffe5]+$");
Pattern pattern=Pattern.compile("^\\d{6}$");
Pattern pattern=Pattern.compile("^[1-9]d{4,9}$");
Pattern pattern=Pattern.compile("^1[3|4|5|8]\\d{9}$");
Pattern pattern=Pattern.compile("^((http|https)://)([\\w-]+\\.)+[\\w-]+(\\/[\\w-?=&/%.#]*)?$");
JDK1.5 引入了枚举类型。枚举类型的定义包括枚举声明和枚举体。格式如下:
enum 枚举名 {
枚举体(常量列表)
}
【示例】创建枚举类型
enum Season {
SPRING, SUMMER, AUTUMN, WINTER
}
所有的枚举类型隐性地继承自 java.lang.Enum。枚举实质上还是类!而每个被枚举的
成员实质就是一个枚举类型的实例,他们默认都是 public static final 修饰的。可以直接通
过枚举类型名使用它们。
【示例】枚举的使用
import java.util.Random; public class TestEnum { public static void main(String[ ] args) { // 枚举遍历 for (Week k : Week.values()) { System.out.println(k); } // switch 语句中使用枚举 int a = new Random().nextInt(4); // 生成 0,1,2,3 的随机数 switch (Season.values()[a]) { case SPRING: System.out.println("春天"); break; case SUMMER: System.out.println("夏天"); break; case AUTUMN: System.out.println("秋天"); break; case WINTER: System.out.println("冬天"); break; } } } /**季节*/ enum Season { SPRING, SUMMER, AUTUMN, WINTER } /**星期*/ enum Week { 星期一, 星期二, 星期三, 星期四, 星期五, 星期六, 星期日 }
【示例】订单状态的枚举
package a_enum; /** * 订单状态: Nonpayment(未付款)、 Paid(已付款) 、 Delivered(已发货)、Return(退货)、 Checked(已确认) Fulfilled(已配货)、 */ public class StateDemo3 { public static void main(String[] args) { OrderState[] states = OrderState.values(); for (int i = 0; i < states.length; i++) { System.out.println(states[i] + "-" + states[i].getValue() + "-" + states[i].getCode()); } } public enum OrderState { //static OrderState NON_PAYMENT = new OrderState("未付款") NON_PAYMENT(1, "未付款"), PAID(2, "已付款"), DELIVERED(3, "已发货"), RETURN(4, "退货"), CHECKED(5, "已确认"), FULFILLED(6, "已配货"); private OrderState(int code, String value) { this.code = code; this.value = value; } private int code; private String value; public String getValue() { return value; } public int getCode() { return code; } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。