1. 接口
广义的接口
在软件工程中,接口泛指供别人调用的方法或者函数。
狭义的接口
接口的关键字是interface
格式
接口中包含什么?
接口中包含变量和方法。
1.1. 什么是接口?
l 接口中的变量会被隐式地指定为public static final变量(并且只能是public static final变量,用private修饰会报编译错误),必须显式初始化
l 接口中的方法会被隐式地指定为public abstract方法且只能是public abstract方法(用其他关键字,比如private、protected、static、 final等修饰会报编译错误)
l 接口中所有的方法不能有具体的实现,也就是说,接口中的方法必须都是抽象方法。
l 接口不可以被实例化 (结论类似 抽象类不能实例化)
l 实现类必须实现接口的所有抽象方法,除非这个类也是抽象类( 结论类似 子类必须实现父类中的所有抽象方法,除非子类也是抽象类)
l 实现类可以实现多个接口 implements ,多个接口使用逗号隔开
l 一个接口不能实现另一个接口,但可以继承多个其他接口
举例1:
/**
* 接口:只能有全局的静态常量 或者全局的抽象方法
* 接口中的变量 一定是全局的静态常量 默认 用public static final 修饰
* 接口中的方法一定是全局的抽象方法 默认用 public abstract 修饰
* 不能出现普通方法 ,静态代码块 ,普通代码块 ,构造
* @author Administrator
*
*/
public interface MyInterface1 {
//int num = 10;
//public static final 写不写都一样,默认会加上
public static final int num=10;
// public abstract 不管写不写,还是没写全,默认都会加上
//void ceshi();
public abstract void ceshi();
//public void ceshi();
//编译错误的情况 r如下
/*public void ceshi2(){
}*/
/*static{
}*/
/*{
}*/
/*public MyInterface1(){
}*/
//protected void ceshi3();
//private void ceshi3();
//static void ceshi3();
//final void ceshi3();
}
举例2:
pac
/**
* 接口支持多继承,一个接口,可以有多个父接口
* 但是类只支持单根继承,1个类只能有1个直接父类
* 1个类可以继承1个父类实现多个接口,实现的多个接口之间,用逗号相隔
* @author Administrator
*
*/
public interface MyInterface3 extends MyInterface1,MyInterface2 {
}
class Animal1 {
}
class Animal2{
}
/*class Dog extends Animal1,Animal2{
}*/
class Dog extends Animal1 implements MyInterface1,MyInterface2,MyInterface3{
@Override
public void ceshi() {
}
@Override
public void ceshi2() {
}
}
初步总结
接口是一种极度抽象的类型,它比抽象类更加“抽象”,并且一般情况下不在接口中定义变量。
要让类实现接口,格式:
访问修饰符(public/default) class 类A extends 父类B implements 接口1,接口2,接口3….{
//…具体实现方法
}
访问修饰符(public/default) interface 接口1 extends 父接口1,父接口2,父接口3….{
}
注意
(1)一个类可以遵循多个接口,如果遵循了一个接口,就必须实现接口中所有的方法
(2)抽象类遵循一个接口,可以不用实现该接口的方法,方法被隐式的加入了抽象类。
案例:实现防盗门功能。
分析:门有“开”和“关”的功能,锁有“上锁”和“开锁”的功能
将门和锁分别定义为抽象类。 发现语法上不行(只能说防盗门继承门(防盗门是一种门 ok),不能说防盗门继承锁(防盗门是一种锁 no))。
解决:将门定义为抽象类,锁定义为接口,防盗门继承门,实现锁的接口。
定义Door 抽象类:具有开门,关门的功能 is-a
定义Lock接口:具备上锁,开锁的能力。has –a ,只能说防盗门上有锁(拥有的关系,而接口体现的是一种能力,实现了锁接口后,就拥有开锁,上锁的能力)
编写TheftproofDoor类 继承抽象类,实现接口
编写测试类:让防盗门关门,上锁,开锁,开门。
扩展,主人,不在家时,按门铃,添加拍照存档的功能,添加门铃接口
package com.interface02.door;
public abstract class Door {
/**
* 关门
*/
public abstract void closeDoor();
/**
* 开门
*/
public abstract void openDoor();
}
package com.interface02.door;
/**
* 锁设计成接口,表示的是一种能力,防盗门装上了锁,拥有开锁,关锁的能力,
* 密码箱 ,保险柜... 都可以实现锁的接口
* @author Administrator
*
*/
public interface Lock {
/**
* 上锁
*/
void lockUp();
/**
* 开锁
*/
void openLock();
}
package com.interface02.door;
/**
* 防盗门类
* @author Administrator
*
*/
public class TheftProofDoor extends Door implements Lock,Bell{
@Override
public void closeDoor() {
System.out.println("轻轻拉门,门关上了");
}
@Override
public void openDoor() {
System.out.println("用力推,门打开了");
}
@Override
public void lockUp() {
System.out.println("插进钥匙,向左转三圈,锁上了,拔出钥匙");
}
@Override
public void openLock() {
System.out.println("插进钥匙,向右转三圈,锁打开了,拔出钥匙");
}
@Override
public void takePhotos() {
System.out.println("喀嚓...主人不在家,对访客拍照存档");
}
}
package com.interface02.door;
/**
* 门铃 设计成接口,表示一种能力,不光防盗门能实现,照相机,手机,都能实现
* @author Administrator
*
*/
public interface Bell {
void takePhotos();
}
package com.interface02.door;
public class TestTheProofDoor {
public static void main(String[] args) {
//注意 既想调用父类中的关门,开门,又想调用接口中的上锁,开锁
//不能 Door lo = new TheftProofDoor(); Lock lo = new TheftProofDoor();
TheftProofDoor lo= new TheftProofDoor();
//上班 关门---上锁 --拍照 ---下标回家--开锁---开门
lo.closeDoor();
lo.lockUp();
lo.takePhotos();
lo.openLock();
lo.openDoor();
}
}
课堂练习2
智能手机 G502C 索尼爱立信 这是一款 型号的品牌的手机 播放的视频 发彩信(只有手机才能发信息) 打电话(视频电话 只有手机才能打电话)
ApptitudePhone
普通手机 I9100 HTC 播放的音乐 发短信 打普通电话(语音电话) commonPhone
手机: 型号 type 品牌 brand public void showInfo(){ //打印 这是一款….的手机 }; public abstract void sendMsg(); // public abstract void call();
带参构造 2个参的
Phone
播放提取成接口 ,因为播放代表一种能力 ,手机可以播放视频,音频,Mp4,Mp3,平板电脑… 都可以播放音频,视频
Interface PlayWiring {
Void play(String content); //content表示的播放的内容名称
}
拍照 提取成接口 ,因为普通手机不能拍照,不能放在父类里作为父类的通用方法 ,拍照代表也是一种能力,不光手机能拍,照相机也能拍
Interface ThePicture{
Void takePhotos(); //提供一个拍照的抽象方法
}
上网 提取成接口 ,上网也表示一种能力,一种功能 ,不能放在父类里做方法,普通手机不能上网 ,电脑,pad只要实现了这个接口,都可以上网
Interface NetWork{
Void connectNet(); //提供一个上网的抽象方法
}
测试类
1.2. 抽象类和接口的区别
(1) 抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
(2) 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
(3) 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
(4) 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
(5) 抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更;而对于接口则不行,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动。
(6) 抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。接口是一个统一规范,它不是为一个类的一个方法服务的,它是对外用来统一口径的,一个招牌。
1.3. 接口的总结(接口有比抽象更好的特性)
1.可以被多继承
2.设计和实现完全分离
3.更自然的使用多态
4.更容易的搭建程序框架
5.更容易更换实现
6.接口是一种约定:有些接口只有名称(Serilizable接口)
7.面向接口编程:程序设计时,面向接口的约定,而不考虑具体实现。
1.4. 接口与抽象类简要对比
相同点:
代表系统的抽象层
都不能被实例化
都能包含抽象方法(用于描述系统提供的服务,不必提供具体实现)
不同点:
在抽象类中可以为部分方法提供默认实现,而接口中只能包含抽象方法。
抽象类便于复用,接口便于代码维护。
一个类只能继承一个直接父类,但可以实现多个接口 。
1.5. 接口使用原则
接口做系统与外界交互的窗口
接口提供服务
接口本身一旦制定,就不允许随意修改
抽象类可完成部分功能实现,还有部分功能可作为系统的扩展点。
练习:
墨盒,纸张,都是行业规范,不能人为更改,只能遵从这种规范去生产,所以墨盒,纸张设计成接口
墨盒,纸张,打印机 关系? 墨盒,纸张是打印机的一部分,用来组装打印机的。看成是打印机类的属性
1.6. 正则是什么?
正则表达式是一种可以用于模式匹配和替换的规范,一个正则表达式就是由普通的字符(例如字符a到z)以及特殊字符(元字符)组成的文字模式,它用以描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。
正则的用途
l 字符串匹配(字符匹配)
l 字符串查找
l 字符串替换
l 字符串分割
Java中处理正则表达式的类
java.lang.String
java.util.regex.Pattern:模式类。字符串要被匹配的这么一个模式,该模式本身已经被编译过,使用的话效率要高很多。
java.util.regex.Matcher:匹配类。这个模式匹配某个字符串所产生的结果,这个结果可能会有很多个。
正则如何使用
总结常用的元字符
. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线
\s 匹配任意的空白符
\d 匹配数字
练习:
(1)使用正则,实现“请告诉我100以内数字之和”。
(2)添加用户时,会输入一个用户名,用户输入用户名后,显示出非法字符。比如输入“&%吴彦祖123abc”,在控制台输出“您输入的&%吴彦祖不是用户名的合法字符。”
区间
总结区间的用法
[abc] a、b或c(简单类)
[^abc] 任何字符,除了a、b或c(否定)
[a-zA-Z] a到z或A到Z,两头的字母包括在内(范围)
[a-d[m-p]] a到d或m到p:[a-dm-p](并集)
[a-z&&[def]] d、e或f(交集)
[a-z&&[^bc]] a到z,除了b和c:[ad-z](减去)
[a-z&&[^m-p]] a到z,而非m到p:[a-lq-z](减去)
重复
总结重复的用法
a?a一次或一次也没有
a*a零次或多次
a+a一次或多次
a{n}? a恰好n次
a{n,}? a至少n次
a{n,m}? a至少n次,但是不超过m次
边界匹配器
^ 开头
$ 结尾
常用的匹配项
一个或多个汉字 ^[\u0391-\uFFE5]+$
邮政编码 ^[1-9]\d{5}$
QQ号码 ^[1-9]\d{4,10}$
邮箱 ^[a-zA-Z_]{1,}[0-9]{0,}@(([a-zA-z0-9]-*){1,}\.){1,3}[a-zA-z\-]{1,}$
用户名(字母开头 + 数字/字母/下划线) ^[A-Za-z][A-Za-z1-9_-]+$
手机号码 ^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$
练习:
(1) 给用户管理系统添加用户名时判断用户名是否满足用户名要求
(2) 给商品增加联系电话属性,添加电话时,判断手机号是否正确
一、校验数字的表达式
1 数字:^[0-9]*$
2 n位的数字:^\d{n}$
3 至少n位的数字:^\d{n,}$
4 m-n位的数字:^\d{m,n}$
5 零和非零开头的数字:^(0|[1-9][0-9]*)$
6 非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$
7 带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})?$
8 正数、负数、和小数:^(\-|\+)?\d+(\.\d+)?$
9 有两位小数的正实数:^[0-9]+(.[0-9]{2})?$
10 有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$
11 非零的正整数:^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$
12 非零的负整数:^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$
13 非负整数:^\d+$ 或 ^[1-9]\d*|0$
14 非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
15 非负浮点数:^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
16 非正浮点数:^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
17 正浮点数:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
18 负浮点数:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
19 浮点数:^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$
二、校验字符的表达式
1 汉字:^[\u4e00-\u9fa5]{0,}$
2 英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
3 长度为3-20的所有字符:^.{3,20}$
4 由26个英文字母组成的字符串:^[A-Za-z]+$
5 由26个大写英文字母组成的字符串:^[A-Z]+$
6 由26个小写英文字母组成的字符串:^[a-z]+$
7 由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
8 由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$
9 中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$
10 中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
11 可以输入含有^%&',;=?$\"等字符:[^%&',;=?$\x22]+
12 禁止输入含有~的字符:[^~\x22]+
三、特殊需求表达式
1 Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
2 域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
3 InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
4 手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
5 电话号码("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX):^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$
6 国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
7 身份证号:
15或18位身份证:^\d{15}|\d{18}$
15位身份证:^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$
18位身份证:^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{4}$
8 短身份证号码(数字、字母x结尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
9 帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
10 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$
11 强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
12 日期格式:^\d{4}-\d{1,2}-\d{1,2}
13 一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$
14 一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$
15 钱的输入格式:
16 1.有四种钱的表示形式我们可以接受:"10000.00" 和 "10,000.00", 和没有 "分" 的 "10000" 和 "10,000":^[1-9][0-9]*$
17 2.这表示任意一个不以0开头的数字,但是,这也意味着一个字符"0"不通过,所以我们采用下面的形式:^(0|[1-9][0-9]*)$
18 3.一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$
19 4.这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧.下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$
20 5.必须说明的是,小数点后面至少应该有1位数,所以"10."是不通过的,但是 "10" 和 "10.2" 是通过的:^[0-9]+(.[0-9]{2})?$
21 6.这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{1,2})?$
22 7.这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$
23 8.1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$
24 备注:这就是最终结果了,别忘了"+"可以用"*"替代如果你觉得空字符串也可以接受的话(奇怪,为什么?)最后,别忘了在用函数时去掉去掉那个反斜杠,一般的错误都在这里
25 xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$
26 中文字符的正则表达式:[\u4e00-\u9fa5]
27 双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1))
28 空白行的正则表达式:\n\s*\r (可以用来删除空白行)
29 HTML标记的正则表达式:<(\S*?)[^>]*>.*?|<.*? /> (网上流传的版本太糟糕,上面这个也仅仅能部分,对于复杂的嵌套标记依旧无能为力)
30 首尾空白字符的正则表达式:^\s*|\s*$或(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式)
31 腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始)
32 中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字)
33 IP地址:\d+\.\d+\.\d+\.\d+ (提取IP地址时有用)
1.7. 常用类
日期相关:Date、SimpleDateFormat、Calendar
Calendar和Date互相转化
使用Calendar计算某一天是一年中的第几星期(比方说2016年11月9号是一年的第多少个星期)
计算一年中的第几星期的星期几是几号(2016年第3个星期的星期1是多少号?)
add()方法加减日期(2016年11月8号加上3天后日期,减去5天后日期)
练习:
在控制台接收输入一个日期,再输入一个增加的天数,输出100天后是什么时间。