正则
检查字符串是否符合定义的规则,这个规则叫正则表达式。
- matches是拿整个测试字符串去验证。
- find是去判断子串是否有匹配。
使用正则的3种方式
String s = "asdfadfadfadsf" ;
// 方式1:
// 定义正则表达式(规则)
Pattern p = Pattern.compile("xxxxxxxxxxxx");
Matcher matcher = p.matcher(s);
// true/false:测试的字符串是否符合定义的规则
// System.out.println(matcher.matches());
// 方式2:
// System.out.println(Pattern.matches("a*b", "aaaaabb"));
// 方式3:
// s.matches("xxxxxxxx");
正则API
System.out.println(Pattern.matches("a*b", "aaaaabb"));//false:n个a,1个b
System.out.println(Pattern.matches("[ab]", "ab"));//false:1个a或1个b
System.out.println(Pattern.matches("[a-zA-H]", "Z"));//false:a-z或A-H中的一个字符
System.out.println(Pattern.matches("[^abc]", "d"));//true:不为a,b,c的任意字符
System.out.println(Pattern.matches("[a-k&&c-z]", "z"));//false
System.out.println(Pattern.matches("a[a-z]c", "abc"));//true
System.out.println(Pattern.matches("\\d", "10"));//false:0-9的1个数字
System.out.println(Pattern.matches("\\D", "a"));//true:不为数字的任意字符
System.out.println(Pattern.matches("\\s", "\t"));//true:1个空格
System.out.println(Pattern.matches("\\S", "a"));//true:不为空格的任意字符
System.out.println(Pattern.matches("\\w", "8"));//true:字母或数字[a-zA-Z_0-9]
System.out.println(Pattern.matches("\\W", "a"));//false:不为字母或数字
System.out.println(Pattern.matches("^a\\d{4}f$", "a1234f"));//true:a+4个数字+f
System.out.println(Pattern.matches("ab?c", "abbbc"));//false:a+0或1个b+c
System.out.println(Pattern.matches("ab*c", "abbbbbbbc"));//true:a+0或n个b+c
System.out.println(Pattern.matches("a\\d+c", "a12312312312c"));//true:a+数字(0-N个)+c
System.out.println(Pattern.matches("a\\d{3}c", "a123c"));//true:数字为3个
System.out.println(Pattern.matches("a\\d{3,}c", "a12312312312c"));//true:数字>=3个
System.out.println(Pattern.matches("a\\d{3,5}c", "a123456c"));//false:数字为[3,5]个
量词跟分组
// Greedy 贪婪的
Pattern p1 = Pattern.compile("a.*b");
// Reluctant 懒惰
Pattern p2 = Pattern.compile("a.*?b");
Matcher matcher1 = p1.matcher("a=======b=========b==========");
if(matcher1.find()){
System.out.println(matcher1.group());//a=======b=========b
}
Matcher matcher2 = p2.matcher("a=======b=========b==========");
if(matcher2.find()){
System.out.println(matcher2.group());//a=======b
}
String s = "2020-08-13";
Pattern p = Pattern.compile("(?<year>\\d{4})-(?<md>(?<month>\\d{2})-(?<day>\\d{2}))");
Matcher matcher = p.matcher(s);
if(matcher.find()){
// 当匹配后,匹配的年份是多少?
// System.out.println(matcher.group());
// 分组:给分组取个名称,通过名称来获取分组的内容
System.out.println(matcher.group("year"));//2020
System.out.println(matcher.group("md"));//08-13
System.out.println(matcher.group("month"));//08
System.out.println(matcher.group("day"));//13
}
String s = "aaaaabaaababaaaabab";
Pattern p = Pattern.compile("a*b");
Matcher matcher = p.matcher(s);
System.out.println(matcher.matches());
matcher.reset();//重置
while(matcher.find()){
System.out.println(matcher.group()+" "+matcher.start()+" "+matcher.end());
// matcher.reset();// 死循环
}
reset重置
案例
输入出生年月计算年龄、生日倒计时
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请按照XXXX-XX-XX输入出生年月日:");
String s = input.next();
Pattern p = Pattern.compile("(?<year>\\d{4})-(?<md>(?<month>\\d{2})-(?<day>\\d{2}))");
Matcher m = p.matcher(s);
Calendar now = Calendar.getInstance();
if(m.find()){
//年龄
System.out.println("年龄:"+(now.get(Calendar.YEAR)-Integer.parseInt(m.group("year"))));
//还有多少天生日
Calendar birth = Calendar.getInstance();
birth.set(Calendar.MONTH, Integer.parseInt(m.group("month"))-1);
birth.set(Calendar.DAY_OF_MONTH, Integer.parseInt(m.group("day")));
long l = birth.getTimeInMillis()-now.getTimeInMillis();
if(l>0){
System.out.println("你还有"+(l/1000/60/60/24)+"天过生日");
}else{
birth.add(Calendar.YEAR, 1);
long l2 = birth.getTimeInMillis()-now.getTimeInMillis();
System.out.println("你还有"+(l2/1000/60/60/24)+"天过生日");
}
}else{
System.out.println("格式有误");
}
}
注解
什么叫注解?
注解是对程序进行解释说明用的。
有哪些注解
- @Override
- @Deprecated
- @SuppressWarnings
元注解
对注解进行注解的。 - @Target
定义这个注解可以写在哪些地方。
如果是一个值直接写,多个值需要用{}括起来。 - @Retention
定义注解的生命周期是什么阶段 - @Documented
生成doc文档的时候是否显示这个注解。 - @Inherited
表示这个注解是否会被继承,修饰类,不能用在接口中
自定义注解
- @interface 表示这是一个注解。
- @Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- @Inherited
public @interface MyAnnotation {
// 参数类型 value参数key
String value() default "";
}
注解的参数
String value() default "";
- String表示的是参数的类型,value表示的是参数的名称。default表示的是没给这个参数使用的默认值。
- 如果没有给默认值,则一定要给这个参数值。默认值不能是null。
- 如果参数名称是value的话,可以省略value。
案例
Person有name属性,自定义一个注解,用户在控制台中输入值用户名。
- 如果这个输入user合法,则赋值给name属性。
- 合法规则:
1,最小长度为注解中minLength参数值
2,最大长度为注解中maxLength参数值
3,用户名必须包含注解中的keyWord的参数值
4,必须包含小写字母、大写字母、数字3选2
如果不合法,提示用户名不合法,再次输入
//注解类:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MyAnnotation {
int maxLength() default 12;
int minLength() default 6;
String keyWord() default "user";
}
public class Person {
@MyAnnotation
private String name;
@Override
public String toString() {
return "Person [name=" + name + "]";
}
}
public class Demo01 {
public static void main(String[] args) throws Exception {
Scanner input = new Scanner(System.in);
System.out.println("请输入用户名");
String userName = input.next();
Class c = Person.class;
Person p = (Person) c.newInstance();//实例化对象
Field f = c.getDeclaredField("name");//获取属性
MyAnnotation ma = f.getAnnotation(MyAnnotation.class);
int min = ma.minLength();
int max = ma.maxLength();
String key = ma.keyWord();
int count = 0;
if(userName.matches(".*[a-z].*")){
count++;
}
if(userName.matches(".*[0-9].*")){
count++;
}
if(userName.matches(".*[A-Z].*")){
count++;
}
if(count>=2&&userName.length()>min&&userName.length()<max&&userName.contains(key)){
f.setAccessible(true);
f.set(p, userName);
System.out.println(p);
}else{
System.out.println("输入格式错误");
}
}
}