【Java】继承与接口

【Java】继承与接口


枚举

什么是枚举

Emum是在Java5中引入的新特性,从那开始,它被广泛的用在不同的Java应用中。Enum是一个Java的关键字,用于表示一个固定的常用值。例如,每周的天数,每年的月数等。Enum是一种类型,就像Class和Interface可以用于定义一系列的Enum常量

枚举的特点

  • Enum常量隐式的加上了static和final,一旦被创建就无法修改,所以是线程安全的
  • Enum提供了是类型安全的(type-safe)
  • Enum隐式的加上了values()方法,返回一个数组包含所有的Enum常量
  • 两个Enum常量可以使用 ==equals()方法比较
  • Enum可以用在switch语句中,就像int,String。
  • Enum有自己的名称空间
  • Enum可以实现Java接口
  • 可以在Enum中定义构造器

所有的enums隐式的extend了java.lang.Enum类,因为一个类只能extend一个父亲,所以enum不能extend其它的类。但是Enum可以实现许多接口。

枚举的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
// 外部声明Enum
enum Color {
RED,GREEN,BLUE;
}
public class Test
{
public static void main(String[] args)
{
Color c1 = Color.RED;
//输出RED
System.out.println(c1);
}
}

枚举的原理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//案例代码
enum AccountType implements Serializable,Cloneable
{
SAVING, FIXED, CURRENT;
private AccountType()
{
System.out.println("It is a account type");
}
}
class Main
{
public static void main(String[]args)
{
System.out.println(AccountType.FIXED);

}
}
//输出结果
It is a account type
It is a account type
It is a account type
FIXED

枚举类在后台实现时,实际上是转化为一个继承了java.lang.Enum类的实体类,原先的枚举类型变成对应的实体类型,上例中AccountType变成了个class AccountType,并且会生成一个新的构造函数,若原来有构造函数,则在此基础上添加两个参数,生成新的构造函数,如上例子中:

1
2
3
private AccountType(){ 
System.out.println(“It is a account type”);
}

会变成:

1
2
3
4
private AccountType(String s, int i){
super(s,i);
System.out.println(“It is a account type”);
}

而在这个类中,会添加若干字段来代表具体的枚举类型:

1
2
3
public static final AccountType SAVING;
public static final AccountType FIXED;
public static final AccountType CURRENT;

而且还会添加一段static代码段:

1
2
3
4
5
static{ 
SAVING = new AccountType("SAVING", 0);
CURRENT = new AccountType("CURRENT", 0);
$VALUES = new AccountType[]{ SAVING, FIXED, CURRENT }
}

以此来初始化枚举中的每个具体类型。(并将所有具体类型放到一个$VALUE数组中,以便用序号访问具体类型)

在初始化过程中new AccountType构造函数被调用了三次,所以Enum中定义的构造函数中的打印代码被执行了3遍。

异常

异常的结构分类

所有的异常都是继承了Thowable

  • Error:是运行时系统错误,或者资源耗尽错误等,是没办法解决的,这时应该通告用户,并尽力使程序安全终止
  • Exception:又分为两种
    1. RuntimeException:当出现这种异常时,一定时程序本身存在问题,可能是错误的类型转换,数组越界,空指针等等
    2. 非RuntimeException:可能是I/O异常,文件不存在,类不存在等等

受检异常和非受检异常

非受检异常指的是java.lang.RuntimeException和java.lang.Error类及其子类,所有其他的异常类都称为受检异常。

那么什么是受检异常和非受检异常呢?

受检异常的特点在于它强制要求开发人员在代码中进行显式的声明和捕获,否则就会产生编译错误。这种限制从好的方面来说,可以防止开发人员意外地忽略某些出错的情况,因为编译器不允许出现未被处理的受检异常

非受检异常的特点是,如果不捕获异常,不会产生编译错误,异常会在运行时刻才被抛出。

异常的用法

throw和throws关键字
Throw用于抛出异常对象,后面跟的时异常对象。是语句抛出一个异常。多用在函数内。

语法:throw(异常对象)

​ throw e;

Throws是方法可能抛出异常的声明(用在声明方法时,表示该方法可能要抛出异常)

语法:修饰符 返回值类型 方法名 参数类型 throws异常类

​ public void test throws Exception1,Exception2(){}

finally关键字

finally声明的代码段中,即使代码已经进入了返回值阶段,也一定会在程序程序末尾执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Main {
public static int getNumber() {
try {
System.out.println("try");
return 1;
} catch (Exception e) {
System.out.println(e);
} finally {
return -1;
}
}

public static void main(String[] args) {
//输出结果-1
System.out.println(getNumber());
}
}

正则表达式

java正则表达式的实现,是利用了java.util.regex包下的Pattern类与Matcher类

Pattern类(制定匹配规则)

  • 创建pattern对象:

    1
    2
    Pattern p=Pattern.compile("\\w+"); 
    p.pattern();//返回 \w+
  • 根据正则分隔字符串:返回一个String[]

    1
    2
    3
    Pattern p=Pattern.compile("\\d+"); 
    String[] str=p.split("我的QQ是:456456我的电话是:0532214我的邮箱是:aaa@aaa.com");
    //结果:str[0]="我的QQ是:" str[1]="我的电话是:" str[2]="我的邮箱是:aaa@aaa.com"
  • Pattern.matcher(String regex,CharSequence input)是一个静态方法,用于快速匹配字符串,该方法适合用于只匹配一次,且匹配全部字符串

    1
    2
    3
    Pattern.matches("\\d+","2223");//返回true 
    Pattern.matches("\\d+","2223aa");//返回false,需要匹配到所有字符串才能返回true,这里aa不能匹配到
    Pattern.matches("\\d+","22bb23");//返回false,需要匹配到所有字符串才能返回true,这里bb不能匹配到
  • 通过pattern返回matcher对象,Matcher类的构造方法也是私有的,不能随意创建,只能通过Pattern.matcher(CharSequence input)方法得到该类的实例.

    1
    2
    3
    Pattern p=Pattern.compile("\\d+"); 
    Matcher m=p.matcher("22bb23");
    m.pattern();//返回p 也就是返回该Matcher对象是由哪个Pattern对象的创建的

Matcher类(查看匹配情况)

  • 查看匹配情况

    1
    2
    3
    4
    5
    Pattern p=Pattern.compile("\\d+"); 
    Matcher m=p.matcher("22bb23");
    m.matches();//返回false,因为bb不能被\d+匹配,导致整个字符串匹配未成功.
    Matcher m2=p.matcher("2223");
    m2.matches();//返回true,因为\d+匹配到了整个字符串
  • lookingAt()对前面的字符串进行匹配,只有匹配到的字符串在最前面才返回true

    1
    2
    3
    4
    5
    Pattern p=Pattern.compile("\\d+"); 
    Matcher m=p.matcher("22bb23");
    m.lookingAt();//返回true,因为\d+匹配到了前面的22
    Matcher m2=p.matcher("aa2223");
    m2.lookingAt();//返回false,因为\d+不能匹配前面的aa
  • find()对字符串进行匹配,匹配到的字符串可以在任何位置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    Pattern p=Pattern.compile("\\d+"); 
    Matcher m=p.matcher("22bb23");
    m.find();//返回true
    Matcher m2=p.matcher("aa2223");
    m2.find();//返回true
    Matcher m3=p.matcher("aa2223bb");
    m3.find();//返回true
    Matcher m4=p.matcher("aabb");
    m4.find();//返回false
  • 返回匹配的位置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    Pattern p=Pattern.compile("\\d+"); 
    Matcher m=p.matcher("aaa2223bb");
    m.find();//匹配2223
    m.start();//返回3
    m.end();//返回7,返回的是2223后的索引号
    m.group();//返回2223

    Mathcer m2=m.matcher("2223bb");
    m.lookingAt(); //匹配2223
    m.start(); //返回0,由于lookingAt()只能匹配前面的字符串,所以当使用lookingAt()匹配时,start()方法总是返回0
    m.end(); //返回4
    m.group(); //返回2223

    Matcher m3=m.matcher("2223bb");
    m.matches(); //匹配整个字符串
    m.start(); //返回0,原因相信大家也清楚了
    m.end(); //返回6,原因相信大家也清楚了,因为matches()需要匹配所有字符串
    m.group(); //返回2223bb
  • groupCount()用于返回有多少组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Pattern p=Pattern.compile("([a-z]+)(\\d+)"); 
    Matcher m=p.matcher("aaa2223bb");
    m.find(); //匹配aaa2223
    m.groupCount(); //返回2,因为有2组
    m.start(1); //返回0 返回第一组匹配到的子字符串在字符串中的索引号
    m.start(2); //返回3
    m.end(1); //返回3 返回第一组匹配到的子字符串的最后一个字符在字符串中的索引位置.
    m.end(2); //返回7
    m.group(1); //返回aaa,返回第一组匹配到的子字符串
    m.group(2); //返回2223,返回第二组匹配到的子字符串

 
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×