Error[8]: Undefined offset: 58, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

Day16 Java 正则表达式、枚举 正则表达式 正则表达式的概述

使用单个字符串来描述或者匹配一系列符合某种语法规则的字符串

正则表达式的使用步骤:

1、通过大量的字符串寻找规律,得出定义规则

2、使用这种规则去匹配新的字符串

3、匹配成功做出相应的 *** 作

学习正则表达式的目的:

通过正则表达式处理字符串复杂的查找/替换/匹配/分割工作

正则表达式是独立于java的技术,不依附于java,但是它可以在java中使用,也可以在python/js等中使用

正则表达式的基本语法: 原义字符:

字符本身就是一个正则表达式

代码举例:

引出String类中的方法:public String replaceAll(String regex,String replacement):

用于替换所有符合规则的字符,用给定的replacement替换与给定的regular expression匹配的此字符串的每个子字符串。

public class RegularDemo2 {
    public static void main(String[] args) {
        String str = "ab123342asdasqwe&;123.";
        String regex = "\.";//代表.这个字符
        System.out.println(str.replaceAll(regex,"_"));//用下划线替换regex的内容

        regex = "b";//代表字符b
        System.out.println(str.replaceAll(regex,"_"));
    }
}

输出结果:由于原字符串中没有b字符,所以输出返回原字符串

 

 元字符:

常用元字符见表格:

字符描述将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'n' 匹配一个换行符。序列 '' 匹配 "" 而 "(" 则匹配 "("。^匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 'n' 或 'r' 之后的位置。$匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 'n' 或 'r' 之前的位置。*匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。+匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。?匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 。? 等价于 {0,1}。{n}n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。{n,}n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。{n,m}m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。?当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。.匹配除换行符(n、r)之外的任何单个字符。要匹配包括 'n' 在内的任何字符,请使用像"(.|n)"的模式。(pattern)匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBscript 中使用 SubMatches 集合,在Jscript 中则使用 (?:pattern)匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。… 属性。要匹配圆括号字符,请使用 '(' 或 ')'。(?=pattern)正向肯定预查(look ahead positive assert),在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,"Windows(?=95|98|NT|2000)"能匹配"Windows2000"中的"Windows",但不能匹配"Windows3.1"中的"Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。(?!pattern)正向否定预查(negative assert),在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如"Windows(?!95|98|NT|2000)"能匹配"Windows3.1"中的"Windows",但不能匹配"Windows2000"中的"Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。(?<=pattern)反向(look behind)肯定预查,与正向肯定预查类似,只是方向相反。例如,"(?<=95|98|NT|2000)Windows"能匹配"2000Windows"中的"Windows",但不能匹配"3.1Windows"中的"Windows"。(?x|y匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"。[xyz]字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。[^xyz]负值字符集合。匹配未包含的任意字符。例如, 'abc' 可以匹配 "plain" 中的'p'、'l'、'i'、'n'。[a-z]字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。[^a-z]负值字符范围。匹配任何不在指定范围内的任意字符。例如,'a-z' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。b匹配一个单词边界,也就是指单词和空格间的位置。例如, 'erb' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。B匹配非单词边界。'erB' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。cx匹配由 x 指明的控制字符。例如, cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。d匹配一个数字字符。等价于 [0-9]。D匹配一个非数字字符。等价于 0-9。f匹配一个换页符。等价于 x0c 和 cL。n匹配一个换行符。等价于 x0a 和 cJ。r匹配一个回车符。等价于 x0d 和 cM。s匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ fnrtv]。S匹配任何非空白字符。等价于 fnrtv。t匹配一个制表符。等价于 x09 和 cI。v匹配一个垂直制表符。等价于 x0b 和 cK。w匹配字母、数字、下划线。等价于'[A-Za-z0-9_]'。W匹配非字母、数字、下划线。等价于 'A-Za-z0-9_'。xn匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,'x41' 匹配 "A"。'x041' 则等价于 'x04' & "1"。正则表达式中可以使用 ASCII 编码。num匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,'(.)1' 匹配两个连续的相同字符。n标识一个八进制转义值或一个向后引用。如果 n 之前至少 n 个获取的子表达式,则 n 为向后引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。nm标识一个八进制转义值或一个向后引用。如果 nm 之前至少有 nm 个获得子表达式,则 nm 为向后引用。如果 nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的向后引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 nm 将匹配八进制转义值 nm。nml如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。un匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如, u00A9 匹配版权符号 (?)。
public class RegularDemo3 {
    public static void main(String[] args) {
        String s = "ab123342asdasqwe&;123.";     
        //只要被匹配的字符串中存在a,b,2中任何一个,都会被匹配到
        String regex = "[ab2]";
        System.out.println(s.replaceAll(regex,"_"));//将匹配到的字符替换为下划线
        //对不是ab2的字符进行匹配
        regex = "[^ab2]";
        System.out.println(s.replaceAll(regex,"_"));
    }
}
 字符类:

表示格式:[]

[]:表示将字符进行归类,可以匹配出现在中括号中的任意字符

例:[123]表示的是只要被匹配的字符串中存在1、2、3中任何一个,都会被匹配到

^:出现在中括号代表的意思是取反,例:[^123]表示对不是1、2、3的字符进行匹配

代码举例:

public class RegularDemo4 {
    public static void main(String[] args) {
        String regex = "[ab]";
        String s = "abcdefghijklmnABCDTW1234DWFadqwr&;123=.";
        System.out.println("匹配之前:" + s);
        System.out.println("=========================================");
        System.out.println(s.replaceAll(regex, "_"));

        //需求:匹配字符串中所有小写的字母
        //[a-z]表示的是匹配a到z中的任意一个小写字母
        regex = "[a-z]";
        System.out.println(s.replaceAll(regex, "_"));

        //[A-Z]表示的是匹配A到Z中的任意一个大写字母
        regex = "[A-Z]";
        System.out.println(s.replaceAll(regex, "_"));

        //又想匹配大写,又想匹配小写?
//        regex = "[a-zA-Z]";这样写是可以的,也可以直接如下面的写法:
        regex = "[A-z]";
        System.out.println(s.replaceAll(regex, "_"));

        //现在想匹配数字怎么办?
        regex = "[0-9]";
        System.out.println(s.replaceAll(regex, "_"));

        //又想匹配数字又想匹配大小写字母,还想匹配&与.
        regex = "[0-z&.]";
        System.out.println(s.replaceAll(regex, "_"));
    }
}

输出结果:

 范围类:

其实就是在字符类的基础上加上了一个范围:

具体看代码举例:

public class RegularDemo5 {
    public static void main(String[] args) {
        String regex = "[0-9]";
        String s = "abcde fghijklmn ABCDTW12.....34D WFadq r&;1!!!!23=.";
        System.out.println("匹配之前:" + s);
        System.out.println("=========================================");
        regex = "\d"; //[0-9]数字
        System.out.println("匹配0到9:");
        System.out.println(s.replaceAll(regex, "_"));

        regex = "\D"; //表示匹配所有非数字的字符
        System.out.println("匹配所有非数字字符:");
        System.out.println(s.replaceAll(regex, "_"));

        regex = "\s"; //匹配所有的空白字符
        System.out.println("匹配所有空白字符:");
        System.out.println(s.replaceAll(regex, "_"));

        regex = "\S"; //匹配所有的除空白字符以外的
        System.out.println("匹配所有非空白字符:");
        System.out.println(s.replaceAll(regex, "_"));

        regex = "\w"; //匹配所有的大小写字母和数字
        System.out.println("匹配所有大小写字母和数字:");
        System.out.println(s.replaceAll(regex, "_"));

        regex = "\W"; //匹配所有的非大小写字母和数字
        System.out.println("匹配所有非大小写字母和数字:");
        System.out.println(s.replaceAll(regex, "_"));

        regex = "."; // 表示的是匹配任意字符
        System.out.println("匹配任意字符:");
        System.out.println(s.replaceAll(regex, "_"));

        regex = "\."; //匹配.这个字符
        System.out.println("匹配字符.:");
        System.out.println(s.replaceAll(regex, "_"));

    }
}

输出结果:

对于上述代码中同时匹配大写字母和小写字母的两种写法的解释:

这种匹配原则是按照ASCII码表进行匹配的,第二种方法与第一种方法的区别是:第二种方法所能匹配的范围更大,因为在ASCII码表中大写字母和小写字母之间并不是连续的,中间有几个字符也可以被匹配到,所以在匹配时若是遇到这些字符也会匹配成功。

预定义类: 

在上一个案例中,为了解决使用范围类实际开发时为了满足一些需求如判断是否是数字、大小写字母等这些情况,所对应的正则表达式会很长而且会出现上文提到的匹配一些实际并不是我们需求中所需要的字符,因此正则表达式整理了一些有特殊含义的表达式:

d == [0-9]数字

D == [^0-9]非数字

s == [rnfr]空白字符

S == [^rnfr]空白字符

w == [a-zA-Z0-9]

W == [^a-zA-Z0-9]

. == 代表任意字符

 具体实现看代码举例:

public class RegularDemo6 {
    public static void main(String[] args) {
        //在没有中括号的时候使用^,^表示的是以xxx开头,这里表示的是以abc开头
        String regex = "^abc";
        String s = "abcdefg";
        System.out.println("匹配之前:" + s);
        System.out.println("=========================================");
        System.out.println("以abc开头:"+s.replaceAll(regex, "_"));

        regex = "fg$";
        System.out.println("以fg结尾:"+s.replaceAll(regex, "_"));
        
        regex = "\b";
        s = "hello worpd 888 1 2 & ; 0 a b c d";
        System.out.println("匹配之前:" + s);
        System.out.println("===========================================");
        System.out.println(s.replaceAll(regex, "_"));

        regex = "\B";
        System.out.println(s.replaceAll(regex, "_"));

    }
}

输出结果:

边界类: 

边界类字符主要有:

^: 不在中括号中出现,表示的是以xxx开头

$: 以xxx结尾

b: 单词边界

B: 非单词边界

 代码举例:

public class RegularDemo7 {
    public static void main(String[] args) {
        //匹配以a开头的0次或者1次
        String regex = "^a?";
        String s = "baaabcdefaaaaaag";
        System.out.println("匹配之前:" + s);
        System.out.println("=======================================");
        System.out.println("a出现0次或1次:"+s.replaceAll(regex, "_"));

        regex = "^a+";
        System.out.println("a出现1次或多次:"+s.replaceAll(regex, "_"));

        regex = "^a*";
        System.out.println("a出现任意次:"+s.replaceAll(regex, "_"));

        //{n}:出现了正好n次
        //需求:匹配一个字符串a字符连续出现了6
        regex = "a{6}"; // aaaaaa
        System.out.println("a连续出现6次:"+s.replaceAll(regex, "*"));

        //{n,m}:出现了n-m次
        regex = "a{3,4}"; // 匹配的是a连续出现的次数在3-4之间
        System.out.println("a出现次数在3-4之间:"+s.replaceAll(regex, "*"));

        //{n, };表示出现了至少n次
        regex = "a{6,}";
        System.out.println("出现了至少n次:"+s.replaceAll(regex, "*"));

        //验证qq
        regex = "[1-9][0-9]{4,9}";
        s = "1165872335";
        System.out.println("验证QQ:"+s.replaceAll(regex, "匹配成功"));
    }
}

输出结果:

量词:

量词主要有:

? : 出现了0次或者1次

+:出现了1次或者多次

*:出现了任意次

{n}:出现了正好n次

{n,m}:出现了n-m次

{n, };表示出现了至少n次

 验证QQ案例:

比较一般做法和使用正则表达式做法:

public class RegularDemo1 {
    public static void main(String[] args) {
        String s = "1165872335";
        //写一个方法去验证这是不是合法的qq
//        System.out.println(checkQQ(s));
        //使用正则处理这样的情况
        System.out.println(checkQQ2(s));
    }

    //正则处理
    public static boolean checkQQ2(String qq){
        //写一个正则表达式
        String regex = "[1-9][0-9]{4,9}";
        return qq.matches(regex);
    }


    
    public static boolean checkQQ(String qq){
        boolean flag = false;
        //1、必须是5-10位
        if(qq.length() >= 5 && qq.length()<=10){
            //2、0不能作为QQ号的开头
            if(!qq.startsWith("0")){
                flag = true;
                //3、必须都是数字
                char[] chars = qq.toCharArray();
                for(int i=0;i 

输出结果:两种结果相同,这里给出正则的结果:

量词的使用代码举例:

public class RegularDemo8 {
    public static void main(String[] args) {
        //它表示匹配的内容是ab加上1-2个c
        String reagex = "abc{1,2}";
        String s = "abcccccABC123ABCabcccccABC123ABCabcccccABC123ABCabcabcabc123";
        System.out.println("匹配之前:n" + s);
        System.out.println("==================================================");
        System.out.println("ab加上1-2个c:"+s.replaceAll(reagex, "_"));

        //加上小括号表示分组
        //表示abc整体出现了1-2次
        reagex = "(abc){1,2}";
        System.out.println("abc整体出现了1-2次:"+s.replaceAll(reagex, "_"));

        reagex = "ABC(abc){1,}";   //ABCabcabc
        System.out.println("ABC加上abc出现一次或多次:"+s.replaceAll(reagex, "_"));

        //matches
        System.out.println("字符串是否匹配到所要匹配的正则:"+s.matches(reagex));
    }
}

输出结果:

分组: 

分组就是使用()将字符串进行分组,也可以表示被()括起来的正则表示一个整体

代码举例:

public class RegularDemo9 {
    public static void main(String[] args) {
        //2022-01-23
        String regex = "(\d{4})-(\d{2})-(\d{2})";
        String s = "2022-01-23  2022-02-24";
        System.out.println(s.replaceAll(regex,"//"));

        //分组中如果我不想让它生成编号,加上?:
        regex = "(\d{4})-(?:\d{2})-(\d{2})";
//        System.out.println(s.replaceAll(regex,"//"));//报错:索引越界
        System.out.println(s.replaceAll(regex,"/"));
    }
}

输出结果:

 

 反向引用:

主要用于取值:

$:取值,取对应分组号中的值,每一个分组的编号从1开始。

代码举例:

需求:2022-01-23 ---> 01/23/2022

import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class RegularDemo10 {
    public static void main(String[] args) {
        String regex = "\w{3,}";
        String s = "abcd123";
        System.out.println(s.matches(regex));

        regex = "[a-z]{2,}";
        s = "abc defg hello111";
        System.out.println(s.replaceAll(regex, "_"));
        System.out.println(s.replaceFirst(regex, "_"));

        s = "abc sbdf 123ab sa123bddss &";
        String[] s1 = s.split(" ");//以空格分割
        //工具类遍历数组,
        System.out.println(Arrays.toString(s1));

        s = "abc sbdf 123ab sa123bddss &";
        String[] s2 = s.split("a");//以a分割
        //工具类遍历数组
        System.out.println(Arrays.toString(s2));

        //Pattern和Matcher
        regex = "\w{3,7}";//匹配3到7个大小写字母或者数字
        Pattern compile = Pattern.compile(regex);
        Matcher matcher = compile.matcher("abcd123");
        System.out.println(matcher.matches());
    }
}

输出结果:

正则表达式在Java中的应用: 

 在java中是如何让使用正则表达式来实现相关 *** 作的?

         1、字符串的查找 *** 作:Pattern和Matcher

         2、字符串的匹配 *** 作:可以使用该字符串的matches方法

         3、字符串的替换 *** 作:字符串String类中有replaceAll()方法和replaceFirst()方法

         4、字符串的分割工作:字符串String类中有split()方法

代码举例:

public class RegularDemo11 {
    public static void main(String[] args) {
        String s = "我我我我我我我..........我.......要要要要要..................要要要要...学习习习习.......习习习习习习习习编程程程程程程.......程程程程程程程程程";
        //1、先将.去掉
        String regex = "\.+";
        String s1 = s.replaceAll(regex, "");
        System.out.println(s1);

        //2、合并叠词
        regex = "(.)+";
        String s2 = s1.replaceAll(regex, "");
        System.out.println(s2);

    }
}

输出结果:

 正则表达式经典练习:

需求:将字符串“我我我我我我我..........我.......要要要要要..................要要要要...学习习习习.......习习习习习习习习编程程程程程程.......程程程程程程程程程”变成“我要学习编程”

 分析:1、先将.....去除,使用"\.+"即可。

2、将叠词只取一个:"(.)\1+",将一个或多个任意字符一个一个分组,再反向引用$1即可。

代码实现:

public class EnumDemo1 {
    public static void main(String[] args) {
        Season spring = Season.SPRING;
        System.out.println(spring);
        System.out.println(spring.getSEASON_NAME());
        System.out.println(spring.getSEASON_DESC());

    }
}

class Season{
    //2、创建Seanson的成员变量,必须把它定义为常量
    private final String SEASON_NAME;
    private final String SEASON_DESC;


    //1、需要将构造方法私有化,保证类的对象的个数是有限个的
    private Season(String SEASON_NAME,String SEASON_DESC){
        this.SEASON_NAME = SEASON_NAME;
        this.SEASON_DESC = SEASON_DESC;
    }

    //3、提供公共的静态的成员变量给外界获取枚举类的对象
    public static final Season SPRING = new Season("春天","春暖花开");
    public static final Season SUMMER = new Season("夏天","烈日炎炎");
    public static final Season AUTUMN = new Season("秋天","秋高气爽");
    public static final Season WINTER = new Season("冬天","白雪皑皑");

    //4、只提供公共的get方法
    public String getSEASON_NAME() {
        return SEASON_NAME;
    }

    public String getSEASON_DESC() {
        return SEASON_DESC;
    }

    //5、重写toString()方法
    @Override
    public String toString() {
        return "Season{" +
                "SEASON_NAME='" + SEASON_NAME + ''' +
                ", SEASON_DESC='" + SEASON_DESC + ''' +
                '}';
    }
}

输出结果:

 枚举类型

1、当一个类的对象只是有限个的时候或者是确定的时候,我们可以将这个类定义为枚举类型

举例:星期,性别,季节,时间,月份等       

2、当需要定义一组常量的时候,强烈建议使用枚举

定义枚举类型:

根据JDK的版本不同,实现的方式不同

1、在JDK1.5之前,自定义一个枚举类

2、在JDK1.5之后,通过java提供了一个叫做enum的关键字创建枚举类

代码举例:

JDK1.5之前,自定义一个枚举类型:以季节为例:

public class EnumDemo2 {
    public static void main(String[] args) {
        Season2 winter = Season2.WINTER;
        System.out.println(winter);
        //java中所有的枚举类都有一个父类:叫做Enum
        System.out.println(Season2.class.getSuperclass());
    }
}

enum Season2{
    //3、提供公共的静态的成员变量给外界获取枚举类的对象
    SPRING("春天","春暖花开"),
    SUMMER("夏天","烈日炎炎"),
    AUTUMN("秋天","秋高气爽"),
    WINTER("冬天","白雪皑皑");


    //2、创建Seanson的成员变量,必须把它定义为常量
    private final String SEASON_NAME;
    private final String SEASON_DESC;


    //1、需要将构造方法私有化,保证类的对象的个数是有限个的
    private Season2(String SEASON_NAME,String SEASON_DESC){
        this.SEASON_NAME = SEASON_NAME;
        this.SEASON_DESC = SEASON_DESC;
    }



    //4、只提供公共的get方法
    public String getSEASON_NAME() {
        return SEASON_NAME;
    }

    public String getSEASON_DESC() {
        return SEASON_DESC;
    }

    //5、重写toString()方法
    @Override
    public String toString() {
        return "Season{" +
                "SEASON_NAME='" + SEASON_NAME + ''' +
                ", SEASON_DESC='" + SEASON_DESC + ''' +
                '}';
    }
}

输出结果:

JDK1.5之后,通过关键字enum定义枚举:

public class EnumDemo3 {
    public static void main(String[] args) {
        Season3 spring = Season3.SPRING;
        System.out.println(spring);// SPRING
        //所有的枚举类都有个父类,叫做Enum
        System.out.println(Season3.class.getSuperclass());
        System.out.println(spring.getSEASON_NAME()+"---"+spring.getSEASON_DESC());
        spring.show();
    }
}
interface Person{
    void show();
}

enum Season3 implements Person{

    //3、提供公共的静态的方法给外界获取枚举类中多个对象
    //将枚举相关的对象放在开头
    SPRING("春天", "春暖花开"),
    SUMMER("夏天", "夏日炎炎"),
    FALL("秋天", "秋高气爽"),
    WINTER("冬天", "白雪皑皑");


    //2、创建枚举类的属性(成员遍历),必须是作为私有常量出现
    private final String SEASON_NAME;
    private final String SEASON_DESC;


    //1、必须将构造方法私有化,这是为了保证类的对象是有限个的目的
    private Season3(String SEASON_NAME,String SEASON_DESC){
        this.SEASON_NAME = SEASON_NAME;
        this.SEASON_DESC = SEASON_DESC;
    }


    //4、提供公共的获取属性的方法
    public String getSEASON_NAME() {
        return SEASON_NAME;
    }

    public String getSEASON_DESC() {
        return SEASON_DESC;
    }

//-----直接在枚举中重写show()方法:-----
    @Override
    public void show() {
        System.out.println("好好学习天天向上");
    }
}

输出结果:

两种区别是使用enum定义枚举省去了public static final Season以及new等修饰符和关键字

枚举实现接口

枚举类型可以实现接口,具体两种方法实现接口:

1、直接在枚举类实现接口中的抽象方法:

public class EnumDemo4 {
    public static void main(String[] args) {
        Season4 spring = Season4.SPRING;
        System.out.println(spring);// SPRING
        //所有的枚举类都有个父类,叫做Enum
        System.out.println(Season4.class.getSuperclass());
        System.out.println(spring.getSEASON_NAME()+"---"+spring.getSEASON_DESC());
        spring.show();

        Season4 winter = Season4.WINTER;
        winter.show();
    }
}
interface Person2{
    void show();
}

enum Season4 implements Person2{

    //4、提供公共的静态的方法给外界获取枚举类中多个对象
    //将枚举相关的对象放在开头

//-----在每个对象内部重写show()方法-----
    SPRING("春天", "春暖花开"){
        @Override
        public void show() {
            System.out.println("出去春游");
        }
    },
    SUMMER("夏天", "夏日炎炎"){
        @Override
        public void show() {
            System.out.println("夏天吃西瓜");
        }
    },
    FALL("秋天", "秋高气爽"){
        @Override
        public void show() {
            System.out.println("秋天中秋吃月饼");
        }
    },
    WINTER("冬天", "白雪皑皑"){
        @Override
        public void show() {
            System.out.println("冬天打雪仗");
        }
    };


    //2、创建枚举类的属性(成员遍历),必须是作为私有常量出现
    private final String SEASON_NAME;
    private final String SEASON_DESC;


    //1、必须将构造方法私有化,这是为了保证类的对象是有限个的目的
    private Season4(String SEASON_NAME,String SEASON_DESC){
        this.SEASON_NAME = SEASON_NAME;
        this.SEASON_DESC = SEASON_DESC;
    }


    //4、提供公共的获取属性的方法
    public String getSEASON_NAME() {
        return SEASON_NAME;
    }

    public String getSEASON_DESC() {
        return SEASON_DESC;
    }
}

输出结果 :

 2、在每个枚举对象中实现 :

[+++]

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Day16 Java 正则表达式、枚举_随笔_内存溢出

Day16 Java 正则表达式、枚举

Day16 Java 正则表达式、枚举,第1张

Day16 Java 正则表达式、枚举 正则表达式 正则表达式的概述

使用单个字符串来描述或者匹配一系列符合某种语法规则的字符串

正则表达式的使用步骤:

1、通过大量的字符串寻找规律,得出定义规则

2、使用这种规则去匹配新的字符串

3、匹配成功做出相应的 *** 作

学习正则表达式的目的:

通过正则表达式处理字符串复杂的查找/替换/匹配/分割工作

正则表达式是独立于java的技术,不依附于java,但是它可以在java中使用,也可以在python/js等中使用

正则表达式的基本语法: 原义字符:

字符本身就是一个正则表达式

代码举例:

引出String类中的方法:public String replaceAll(String regex,String replacement):

用于替换所有符合规则的字符,用给定的replacement替换与给定的regular expression匹配的此字符串的每个子字符串。

public class RegularDemo2 {
    public static void main(String[] args) {
        String str = "ab123342asdasqwe&;123.";
        String regex = "\.";//代表.这个字符
        System.out.println(str.replaceAll(regex,"_"));//用下划线替换regex的内容

        regex = "b";//代表字符b
        System.out.println(str.replaceAll(regex,"_"));
    }
}

输出结果:由于原字符串中没有b字符,所以输出返回原字符串

 

 元字符:

常用元字符见表格:

字符描述将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'n' 匹配一个换行符。序列 '' 匹配 "" 而 "(" 则匹配 "("。^匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 'n' 或 'r' 之后的位置。$匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 'n' 或 'r' 之前的位置。*匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。+匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。?匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 。? 等价于 {0,1}。{n}n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。{n,}n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。{n,m}m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。?当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。.匹配除换行符(n、r)之外的任何单个字符。要匹配包括 'n' 在内的任何字符,请使用像"(.|n)"的模式。(pattern)匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBscript 中使用 SubMatches 集合,在Jscript 中则使用 (?:pattern)匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。… 属性。要匹配圆括号字符,请使用 '(' 或 ')'。(?=pattern)正向肯定预查(look ahead positive assert),在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,"Windows(?=95|98|NT|2000)"能匹配"Windows2000"中的"Windows",但不能匹配"Windows3.1"中的"Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。(?!pattern)正向否定预查(negative assert),在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如"Windows(?!95|98|NT|2000)"能匹配"Windows3.1"中的"Windows",但不能匹配"Windows2000"中的"Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。(?<=pattern)反向(look behind)肯定预查,与正向肯定预查类似,只是方向相反。例如,"(?<=95|98|NT|2000)Windows"能匹配"2000Windows"中的"Windows",但不能匹配"3.1Windows"中的"Windows"。(?x|y匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"。[xyz]字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。[^xyz]负值字符集合。匹配未包含的任意字符。例如, 'abc' 可以匹配 "plain" 中的'p'、'l'、'i'、'n'。[a-z]字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。[^a-z]负值字符范围。匹配任何不在指定范围内的任意字符。例如,'a-z' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。b匹配一个单词边界,也就是指单词和空格间的位置。例如, 'erb' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。B匹配非单词边界。'erB' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。cx匹配由 x 指明的控制字符。例如, cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。d匹配一个数字字符。等价于 [0-9]。D匹配一个非数字字符。等价于 0-9。f匹配一个换页符。等价于 x0c 和 cL。n匹配一个换行符。等价于 x0a 和 cJ。r匹配一个回车符。等价于 x0d 和 cM。s匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ fnrtv]。S匹配任何非空白字符。等价于 fnrtv。t匹配一个制表符。等价于 x09 和 cI。v匹配一个垂直制表符。等价于 x0b 和 cK。w匹配字母、数字、下划线。等价于'[A-Za-z0-9_]'。W匹配非字母、数字、下划线。等价于 'A-Za-z0-9_'。xn匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,'x41' 匹配 "A"。'x041' 则等价于 'x04' & "1"。正则表达式中可以使用 ASCII 编码。num匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,'(.)1' 匹配两个连续的相同字符。n标识一个八进制转义值或一个向后引用。如果 n 之前至少 n 个获取的子表达式,则 n 为向后引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。nm标识一个八进制转义值或一个向后引用。如果 nm 之前至少有 nm 个获得子表达式,则 nm 为向后引用。如果 nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的向后引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 nm 将匹配八进制转义值 nm。nml如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。un匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如, u00A9 匹配版权符号 (?)。
public class RegularDemo3 {
    public static void main(String[] args) {
        String s = "ab123342asdasqwe&;123.";     
        //只要被匹配的字符串中存在a,b,2中任何一个,都会被匹配到
        String regex = "[ab2]";
        System.out.println(s.replaceAll(regex,"_"));//将匹配到的字符替换为下划线
        //对不是ab2的字符进行匹配
        regex = "[^ab2]";
        System.out.println(s.replaceAll(regex,"_"));
    }
}
 字符类:

表示格式:[]

[]:表示将字符进行归类,可以匹配出现在中括号中的任意字符

例:[123]表示的是只要被匹配的字符串中存在1、2、3中任何一个,都会被匹配到

^:出现在中括号代表的意思是取反,例:[^123]表示对不是1、2、3的字符进行匹配

代码举例:

public class RegularDemo4 {
    public static void main(String[] args) {
        String regex = "[ab]";
        String s = "abcdefghijklmnABCDTW1234DWFadqwr&;123=.";
        System.out.println("匹配之前:" + s);
        System.out.println("=========================================");
        System.out.println(s.replaceAll(regex, "_"));

        //需求:匹配字符串中所有小写的字母
        //[a-z]表示的是匹配a到z中的任意一个小写字母
        regex = "[a-z]";
        System.out.println(s.replaceAll(regex, "_"));

        //[A-Z]表示的是匹配A到Z中的任意一个大写字母
        regex = "[A-Z]";
        System.out.println(s.replaceAll(regex, "_"));

        //又想匹配大写,又想匹配小写?
//        regex = "[a-zA-Z]";这样写是可以的,也可以直接如下面的写法:
        regex = "[A-z]";
        System.out.println(s.replaceAll(regex, "_"));

        //现在想匹配数字怎么办?
        regex = "[0-9]";
        System.out.println(s.replaceAll(regex, "_"));

        //又想匹配数字又想匹配大小写字母,还想匹配&与.
        regex = "[0-z&.]";
        System.out.println(s.replaceAll(regex, "_"));
    }
}

输出结果:

 范围类:

其实就是在字符类的基础上加上了一个范围:

具体看代码举例:

public class RegularDemo5 {
    public static void main(String[] args) {
        String regex = "[0-9]";
        String s = "abcde fghijklmn ABCDTW12.....34D WFadq r&;1!!!!23=.";
        System.out.println("匹配之前:" + s);
        System.out.println("=========================================");
        regex = "\d"; //[0-9]数字
        System.out.println("匹配0到9:");
        System.out.println(s.replaceAll(regex, "_"));

        regex = "\D"; //表示匹配所有非数字的字符
        System.out.println("匹配所有非数字字符:");
        System.out.println(s.replaceAll(regex, "_"));

        regex = "\s"; //匹配所有的空白字符
        System.out.println("匹配所有空白字符:");
        System.out.println(s.replaceAll(regex, "_"));

        regex = "\S"; //匹配所有的除空白字符以外的
        System.out.println("匹配所有非空白字符:");
        System.out.println(s.replaceAll(regex, "_"));

        regex = "\w"; //匹配所有的大小写字母和数字
        System.out.println("匹配所有大小写字母和数字:");
        System.out.println(s.replaceAll(regex, "_"));

        regex = "\W"; //匹配所有的非大小写字母和数字
        System.out.println("匹配所有非大小写字母和数字:");
        System.out.println(s.replaceAll(regex, "_"));

        regex = "."; // 表示的是匹配任意字符
        System.out.println("匹配任意字符:");
        System.out.println(s.replaceAll(regex, "_"));

        regex = "\."; //匹配.这个字符
        System.out.println("匹配字符.:");
        System.out.println(s.replaceAll(regex, "_"));

    }
}

输出结果:

对于上述代码中同时匹配大写字母和小写字母的两种写法的解释:

这种匹配原则是按照ASCII码表进行匹配的,第二种方法与第一种方法的区别是:第二种方法所能匹配的范围更大,因为在ASCII码表中大写字母和小写字母之间并不是连续的,中间有几个字符也可以被匹配到,所以在匹配时若是遇到这些字符也会匹配成功。

预定义类: 

在上一个案例中,为了解决使用范围类实际开发时为了满足一些需求如判断是否是数字、大小写字母等这些情况,所对应的正则表达式会很长而且会出现上文提到的匹配一些实际并不是我们需求中所需要的字符,因此正则表达式整理了一些有特殊含义的表达式:

d == [0-9]数字

D == [^0-9]非数字

s == [rnfr]空白字符

S == [^rnfr]空白字符

w == [a-zA-Z0-9]

W == [^a-zA-Z0-9]

. == 代表任意字符

 具体实现看代码举例:

public class RegularDemo6 {
    public static void main(String[] args) {
        //在没有中括号的时候使用^,^表示的是以xxx开头,这里表示的是以abc开头
        String regex = "^abc";
        String s = "abcdefg";
        System.out.println("匹配之前:" + s);
        System.out.println("=========================================");
        System.out.println("以abc开头:"+s.replaceAll(regex, "_"));

        regex = "fg$";
        System.out.println("以fg结尾:"+s.replaceAll(regex, "_"));
        
        regex = "\b";
        s = "hello worpd 888 1 2 & ; 0 a b c d";
        System.out.println("匹配之前:" + s);
        System.out.println("===========================================");
        System.out.println(s.replaceAll(regex, "_"));

        regex = "\B";
        System.out.println(s.replaceAll(regex, "_"));

    }
}

输出结果:

边界类: 

边界类字符主要有:

^: 不在中括号中出现,表示的是以xxx开头

$: 以xxx结尾

b: 单词边界

B: 非单词边界

 代码举例:

public class RegularDemo7 {
    public static void main(String[] args) {
        //匹配以a开头的0次或者1次
        String regex = "^a?";
        String s = "baaabcdefaaaaaag";
        System.out.println("匹配之前:" + s);
        System.out.println("=======================================");
        System.out.println("a出现0次或1次:"+s.replaceAll(regex, "_"));

        regex = "^a+";
        System.out.println("a出现1次或多次:"+s.replaceAll(regex, "_"));

        regex = "^a*";
        System.out.println("a出现任意次:"+s.replaceAll(regex, "_"));

        //{n}:出现了正好n次
        //需求:匹配一个字符串a字符连续出现了6
        regex = "a{6}"; // aaaaaa
        System.out.println("a连续出现6次:"+s.replaceAll(regex, "*"));

        //{n,m}:出现了n-m次
        regex = "a{3,4}"; // 匹配的是a连续出现的次数在3-4之间
        System.out.println("a出现次数在3-4之间:"+s.replaceAll(regex, "*"));

        //{n, };表示出现了至少n次
        regex = "a{6,}";
        System.out.println("出现了至少n次:"+s.replaceAll(regex, "*"));

        //验证qq
        regex = "[1-9][0-9]{4,9}";
        s = "1165872335";
        System.out.println("验证QQ:"+s.replaceAll(regex, "匹配成功"));
    }
}

输出结果:

量词:

量词主要有:

? : 出现了0次或者1次

+:出现了1次或者多次

*:出现了任意次

{n}:出现了正好n次

{n,m}:出现了n-m次

{n, };表示出现了至少n次

 验证QQ案例:

比较一般做法和使用正则表达式做法:

public class RegularDemo1 {
    public static void main(String[] args) {
        String s = "1165872335";
        //写一个方法去验证这是不是合法的qq
//        System.out.println(checkQQ(s));
        //使用正则处理这样的情况
        System.out.println(checkQQ2(s));
    }

    //正则处理
    public static boolean checkQQ2(String qq){
        //写一个正则表达式
        String regex = "[1-9][0-9]{4,9}";
        return qq.matches(regex);
    }


    
    public static boolean checkQQ(String qq){
        boolean flag = false;
        //1、必须是5-10位
        if(qq.length() >= 5 && qq.length()<=10){
            //2、0不能作为QQ号的开头
            if(!qq.startsWith("0")){
                flag = true;
                //3、必须都是数字
                char[] chars = qq.toCharArray();
                for(int i=0;i 

输出结果:两种结果相同,这里给出正则的结果:

量词的使用代码举例:

public class RegularDemo8 {
    public static void main(String[] args) {
        //它表示匹配的内容是ab加上1-2个c
        String reagex = "abc{1,2}";
        String s = "abcccccABC123ABCabcccccABC123ABCabcccccABC123ABCabcabcabc123";
        System.out.println("匹配之前:n" + s);
        System.out.println("==================================================");
        System.out.println("ab加上1-2个c:"+s.replaceAll(reagex, "_"));

        //加上小括号表示分组
        //表示abc整体出现了1-2次
        reagex = "(abc){1,2}";
        System.out.println("abc整体出现了1-2次:"+s.replaceAll(reagex, "_"));

        reagex = "ABC(abc){1,}";   //ABCabcabc
        System.out.println("ABC加上abc出现一次或多次:"+s.replaceAll(reagex, "_"));

        //matches
        System.out.println("字符串是否匹配到所要匹配的正则:"+s.matches(reagex));
    }
}

输出结果:

分组: 

分组就是使用()将字符串进行分组,也可以表示被()括起来的正则表示一个整体

代码举例:

public class RegularDemo9 {
    public static void main(String[] args) {
        //2022-01-23
        String regex = "(\d{4})-(\d{2})-(\d{2})";
        String s = "2022-01-23  2022-02-24";
        System.out.println(s.replaceAll(regex,"//"));

        //分组中如果我不想让它生成编号,加上?:
        regex = "(\d{4})-(?:\d{2})-(\d{2})";
//        System.out.println(s.replaceAll(regex,"//"));//报错:索引越界
        System.out.println(s.replaceAll(regex,"/"));
    }
}

输出结果:

 

 反向引用:

主要用于取值:

$:取值,取对应分组号中的值,每一个分组的编号从1开始。

代码举例:

需求:2022-01-23 ---> 01/23/2022

import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class RegularDemo10 {
    public static void main(String[] args) {
        String regex = "\w{3,}";
        String s = "abcd123";
        System.out.println(s.matches(regex));

        regex = "[a-z]{2,}";
        s = "abc defg hello111";
        System.out.println(s.replaceAll(regex, "_"));
        System.out.println(s.replaceFirst(regex, "_"));

        s = "abc sbdf 123ab sa123bddss &";
        String[] s1 = s.split(" ");//以空格分割
        //工具类遍历数组,
        System.out.println(Arrays.toString(s1));

        s = "abc sbdf 123ab sa123bddss &";
        String[] s2 = s.split("a");//以a分割
        //工具类遍历数组
        System.out.println(Arrays.toString(s2));

        //Pattern和Matcher
        regex = "\w{3,7}";//匹配3到7个大小写字母或者数字
        Pattern compile = Pattern.compile(regex);
        Matcher matcher = compile.matcher("abcd123");
        System.out.println(matcher.matches());
    }
}

输出结果:

正则表达式在Java中的应用: 

 在java中是如何让使用正则表达式来实现相关 *** 作的?

         1、字符串的查找 *** 作:Pattern和Matcher

         2、字符串的匹配 *** 作:可以使用该字符串的matches方法

         3、字符串的替换 *** 作:字符串String类中有replaceAll()方法和replaceFirst()方法

         4、字符串的分割工作:字符串String类中有split()方法

代码举例:

public class RegularDemo11 {
    public static void main(String[] args) {
        String s = "我我我我我我我..........我.......要要要要要..................要要要要...学习习习习.......习习习习习习习习编程程程程程程.......程程程程程程程程程";
        //1、先将.去掉
        String regex = "\.+";
        String s1 = s.replaceAll(regex, "");
        System.out.println(s1);

        //2、合并叠词
        regex = "(.)+";
        String s2 = s1.replaceAll(regex, "");
        System.out.println(s2);

    }
}

输出结果:

 正则表达式经典练习:

需求:将字符串“我我我我我我我..........我.......要要要要要..................要要要要...学习习习习.......习习习习习习习习编程程程程程程.......程程程程程程程程程”变成“我要学习编程”

 分析:1、先将.....去除,使用"\.+"即可。

2、将叠词只取一个:"(.)\1+",将一个或多个任意字符一个一个分组,再反向引用$1即可。

代码实现:

public class EnumDemo1 {
    public static void main(String[] args) {
        Season spring = Season.SPRING;
        System.out.println(spring);
        System.out.println(spring.getSEASON_NAME());
        System.out.println(spring.getSEASON_DESC());

    }
}

class Season{
    //2、创建Seanson的成员变量,必须把它定义为常量
    private final String SEASON_NAME;
    private final String SEASON_DESC;


    //1、需要将构造方法私有化,保证类的对象的个数是有限个的
    private Season(String SEASON_NAME,String SEASON_DESC){
        this.SEASON_NAME = SEASON_NAME;
        this.SEASON_DESC = SEASON_DESC;
    }

    //3、提供公共的静态的成员变量给外界获取枚举类的对象
    public static final Season SPRING = new Season("春天","春暖花开");
    public static final Season SUMMER = new Season("夏天","烈日炎炎");
    public static final Season AUTUMN = new Season("秋天","秋高气爽");
    public static final Season WINTER = new Season("冬天","白雪皑皑");

    //4、只提供公共的get方法
    public String getSEASON_NAME() {
        return SEASON_NAME;
    }

    public String getSEASON_DESC() {
        return SEASON_DESC;
    }

    //5、重写toString()方法
    @Override
    public String toString() {
        return "Season{" +
                "SEASON_NAME='" + SEASON_NAME + ''' +
                ", SEASON_DESC='" + SEASON_DESC + ''' +
                '}';
    }
}

输出结果:

 枚举类型

1、当一个类的对象只是有限个的时候或者是确定的时候,我们可以将这个类定义为枚举类型

举例:星期,性别,季节,时间,月份等       

2、当需要定义一组常量的时候,强烈建议使用枚举

定义枚举类型:

根据JDK的版本不同,实现的方式不同

1、在JDK1.5之前,自定义一个枚举类

2、在JDK1.5之后,通过java提供了一个叫做enum的关键字创建枚举类

代码举例:

JDK1.5之前,自定义一个枚举类型:以季节为例:

public class EnumDemo2 {
    public static void main(String[] args) {
        Season2 winter = Season2.WINTER;
        System.out.println(winter);
        //java中所有的枚举类都有一个父类:叫做Enum
        System.out.println(Season2.class.getSuperclass());
    }
}

enum Season2{
    //3、提供公共的静态的成员变量给外界获取枚举类的对象
    SPRING("春天","春暖花开"),
    SUMMER("夏天","烈日炎炎"),
    AUTUMN("秋天","秋高气爽"),
    WINTER("冬天","白雪皑皑");


    //2、创建Seanson的成员变量,必须把它定义为常量
    private final String SEASON_NAME;
    private final String SEASON_DESC;


    //1、需要将构造方法私有化,保证类的对象的个数是有限个的
    private Season2(String SEASON_NAME,String SEASON_DESC){
        this.SEASON_NAME = SEASON_NAME;
        this.SEASON_DESC = SEASON_DESC;
    }



    //4、只提供公共的get方法
    public String getSEASON_NAME() {
        return SEASON_NAME;
    }

    public String getSEASON_DESC() {
        return SEASON_DESC;
    }

    //5、重写toString()方法
    @Override
    public String toString() {
        return "Season{" +
                "SEASON_NAME='" + SEASON_NAME + ''' +
                ", SEASON_DESC='" + SEASON_DESC + ''' +
                '}';
    }
}

输出结果:

JDK1.5之后,通过关键字enum定义枚举:

public class EnumDemo3 {
    public static void main(String[] args) {
        Season3 spring = Season3.SPRING;
        System.out.println(spring);// SPRING
        //所有的枚举类都有个父类,叫做Enum
        System.out.println(Season3.class.getSuperclass());
        System.out.println(spring.getSEASON_NAME()+"---"+spring.getSEASON_DESC());
        spring.show();
    }
}
interface Person{
    void show();
}

enum Season3 implements Person{

    //3、提供公共的静态的方法给外界获取枚举类中多个对象
    //将枚举相关的对象放在开头
    SPRING("春天", "春暖花开"),
    SUMMER("夏天", "夏日炎炎"),
    FALL("秋天", "秋高气爽"),
    WINTER("冬天", "白雪皑皑");


    //2、创建枚举类的属性(成员遍历),必须是作为私有常量出现
    private final String SEASON_NAME;
    private final String SEASON_DESC;


    //1、必须将构造方法私有化,这是为了保证类的对象是有限个的目的
    private Season3(String SEASON_NAME,String SEASON_DESC){
        this.SEASON_NAME = SEASON_NAME;
        this.SEASON_DESC = SEASON_DESC;
    }


    //4、提供公共的获取属性的方法
    public String getSEASON_NAME() {
        return SEASON_NAME;
    }

    public String getSEASON_DESC() {
        return SEASON_DESC;
    }

//-----直接在枚举中重写show()方法:-----
    @Override
    public void show() {
        System.out.println("好好学习天天向上");
    }
}

输出结果:

两种区别是使用enum定义枚举省去了public static final Season以及new等修饰符和关键字

枚举实现接口

枚举类型可以实现接口,具体两种方法实现接口:

1、直接在枚举类实现接口中的抽象方法:

public class EnumDemo4 {
    public static void main(String[] args) {
        Season4 spring = Season4.SPRING;
        System.out.println(spring);// SPRING
        //所有的枚举类都有个父类,叫做Enum
        System.out.println(Season4.class.getSuperclass());
        System.out.println(spring.getSEASON_NAME()+"---"+spring.getSEASON_DESC());
        spring.show();

        Season4 winter = Season4.WINTER;
        winter.show();
    }
}
interface Person2{
    void show();
}

enum Season4 implements Person2{

    //4、提供公共的静态的方法给外界获取枚举类中多个对象
    //将枚举相关的对象放在开头

//-----在每个对象内部重写show()方法-----
    SPRING("春天", "春暖花开"){
        @Override
        public void show() {
            System.out.println("出去春游");
        }
    },
    SUMMER("夏天", "夏日炎炎"){
        @Override
        public void show() {
            System.out.println("夏天吃西瓜");
        }
    },
    FALL("秋天", "秋高气爽"){
        @Override
        public void show() {
            System.out.println("秋天中秋吃月饼");
        }
    },
    WINTER("冬天", "白雪皑皑"){
        @Override
        public void show() {
            System.out.println("冬天打雪仗");
        }
    };


    //2、创建枚举类的属性(成员遍历),必须是作为私有常量出现
    private final String SEASON_NAME;
    private final String SEASON_DESC;


    //1、必须将构造方法私有化,这是为了保证类的对象是有限个的目的
    private Season4(String SEASON_NAME,String SEASON_DESC){
        this.SEASON_NAME = SEASON_NAME;
        this.SEASON_DESC = SEASON_DESC;
    }


    //4、提供公共的获取属性的方法
    public String getSEASON_NAME() {
        return SEASON_NAME;
    }

    public String getSEASON_DESC() {
        return SEASON_DESC;
    }
}

输出结果 :

 2、在每个枚举对象中实现 :

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5712739.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存