在jdk1.8前:常量 和 抽象方法
成员都是公共的,修饰也是固定的
实现类必须实现所有的抽象方法,否则还是抽象类
在jdk1.8后:允许有带有方法体的方法。
默认方法 default修饰
静态方法 static修饰
1.实现类可以重写也可以不重写
2.实现类中可以直接调用默认方法
3.重写了默认方法,想要调用父接口中的,父接口名.super.默认方法名().
4.实现类实现了多个接口,接口中有相同的方法定义,实现类必须重写该方法
想要调用某个父接口中的默认方法,父接口名.super.默认方法名().
5.一个类继承了一个父类并实现了接口,父类和父接口中有相同的默认方法,优先找类
这样定义接口,发现接口与抽象类越来越像,因此接口有要替代抽象类的趋势。
因此类和类是继承,耦合度高,接口和类是实现关系,耦合度要低。
接口名.静态方法名。
静态方法不被实现类继承,因此实现类不能调用。
静态方法只能访问静态,非静态既可以访问静态也可以访问非静态。
jdk9.0:
接口中可以有私有方法。
这种方法就是只能在当前接口中使用,外部其他类不让其使用。
概念: 接口中有且只有一个抽象方法的,叫做函数式接口(默认方法和静态不考虑)
使用Lambda表达式的前提就是该接口是一个函数式接口。
验证一个接口是否是函数式接口: @FunctionalInterface
在定义接口的上边(interface),写该注解,如果是编译没问题,如果不是,编译时期就报错
自定义函数式接口:
@FunctionalInterface
修饰符 interface 接口名
抽象方法; 1个
默认方法 多个
静态方法 多个
}
public class Demo3 { public static void main(String[] args) { //调用方法 String s = toUpperStr("hello", new ImInter() { @Override public String method(String s) { return s.toUpperCase(); } }); String s1 = toUpperStr("world", ss -> ss.toUpperCase()); System.out.println(s1); } //定义方法,将参数上的字符串转为大写形式 public static String toUpperStr(String str,ImInter im){ return im.method(str); } } //自定义函数式接口 @FunctionalInterface interface ImInter { T method(T t); default void show(){} static void function(){} }
消费型接口: Consumer.andThen先执行左边,再执行右边
Consumer
void accept(T t) :对t进行处理操作,操作完成后就结束。
//打印字符串的长度 Consumercon = s -> System.out.println(s.length()); con.accept("asd");
函数型(功能型)接口:
Function
R apply(T t) : 对t进行各种计算,最终得到一个R类型的结果
//将字符串变成大写形式 Functionfun = s -> s.toUpperCase(); System.out.println(fun.apply("abc"));
断言型接口: Predicate 的 and 与 or 或 negate 非
Predicate
boolean test(T t):对t进行各种判断,最终得到一个boolean类型的结果。
//判断字符串的长度是否大于5 Predicatepre = s -> s.length() > 5; System.out.println(pre.test("asdaffd"));
供给型接口:
Supplier
T get(): 返回T类型数据
//返回字符串abc Suppliersu = () -> "abc"; System.out.println(su.get());
Lambda表达式出现是模拟的数学中的函数,数学中的函数最终会有一个结果,即是一个数值,Lambda表达式最终也会有一个值。实际就是一个匿名实现类的对象,也就是匿名内部类的简写格式,也可以当做一个数据直接进行传递。
好处:代码简洁,效率高(不会有对应的class文件去创建)
前提:有接口,接口中有且只有一个抽象方法(默认方法和静态方法不考虑)
格式:(参数列表) -> {方法体语句;};
说明:
(参数列表) : 接口中的抽象方法的参数列表
-> :Lambda表达式的固定符号
{方法体语句;} : 接口中抽象方法的具体实现代码
new Thread (()->System.out.println("哈哈哈")).start();
Consumercon = s -> System.out.println(s.length()); con.accept("asd");
Callablecall = ()->"hello"; System.out.println(call.call());
Comparatorcom = (Integer a , Integer b ) -> Integer.compare(a,b);
省略规则:
1.左右各为一的时候可以省略对应的括号
2.左侧的参数类型可以省略,注意没有参数小括号不能省略
3.右侧语句大于等于2的时候不能省略大括号
4.有return,并且只有一条语句,那么return和大括号一起省略
可以对数据源进行想要的计算,比如:过滤、去重复..,最终返回的是一个新的Stream。
1.不会改变数据源,而是得到新的Stream。
2.可以对数据源进行一系列流水线似的操作(类似于车间)
3.是一个惰性求值,只有看到终止命令才进行一系列的流水线计算
4.数据源是:数组或集合
5.数据源是存储数据的,而Stream是用来做计算的
6.Stream一旦执行了终止操作,Stream不可以再使用。
1.获取Stream对象 2.一系列流水线似的操作(方法) 3.终止操作
说明:不是一定要有流水线操作,可以只有第一步和第三步
只有1和2步,没有3步,那么不做计算。
获取Stream对象:
包名:java.util.stream;
Collection.stream()
Arrays.stream()
Stream.of()
Map.keySet().stream()
Map.values().stream()
Map.entrySet().stream()
Streams1 = list.stream(); //list 方法 Stream s2 = Stream.of(arr); //Stream类 方法 Stream s3 = Arrays.stream(arr); //数组方法
中间操作:
filter(Predicate) :过滤
获取到Stream对象,相当于有了数据源中的所有数据,每个数据会进行filter计算
符合就要,不符合不要,因此得到的新的Stream中存储的就是满足要求的数据。
distinct() :去重
map(Function) : 对数据运行function的计算操作
limit(int num) : 从0-num个
skip(int num) :从num--末尾个
sorted()
sorted(Comparator)
终止方法:
foreach(Consumer)
count(): 统计个数
collect(Collctor):收集
Annotation,称之为叫做元数据,属于一种代码级别的注释。在jdk5.0版本新增的一个特性。与类、接口、枚举是同级别的,可以使用在类、方法、属性、参数、局部变量、包的前边,可以参与代码的执行。
1.替代配置文件 (eg:Servlet xml 注解)
2.制作帮助文档(javadoc) @author @since...
3.在编译时期做检测 @Override @FunctionalInterface...
常见注解:
@Override @FunctionalInterface @Deprecated(已过时方法,不建议使用) @Test...
修饰注解的注解。
@Target 被修饰的注解能在哪里使用
常用的值: ElementType.TYPE
ELementType.METHOD...
@Retention 被修饰的注解的生命周期
RetentionPolicy.SOUCE:参与编译,但不在class文件中
RetentionPolicy.CLASS:参与编译,在class中,但是不执行
RetentionPolicy.RUNTIME:参与编译和运行
@Documented 是否参与生成版主文档
@Inherited 是否被继承
格式:
修饰符 @interface 注解名{
属性;...
}
注解其实一个接口,是java.lang.annotation.Anotationde的子接口。
编写是不要手动写继承,编译器会自动补全。
属性:可以参与执行,因此作用是用来传递参数数据的,使注解的功能增强。
格式:
数据类型 属性名();
数据类型 属性名() default 数据值;
注解中一旦有属性,这个属性没有默认值,那么使用时必须给属性赋值
如果有默认值,赋值不赋值都可以。
数据类型:
基本类型、String、枚举、Class、注解.
以上这些类型的数组形式。
特殊属性名:
value:在使用时可以省略value=,直接写属性值即可,哪怕是数组形式也是如此。
还有其他属性,这些属性都有默认值,那么可以省略value=,前提是这些属性不重新
赋值。其他属性至少有一个没有默认值,必须写上value=
反射注解:
1.获取使用注解的类的Class对象
2.获取使用注解的成员对象
3.获取对应的注解
public static void main(String[] args) throws NoSuchMethodException { //获取CLASS对象 Classc = Demo1.class; //获取方法 Method m = c.getDeclaredMethod("show"); //获取方法的注解 Myinter1 annotation = m.getAnnotation(Myinter1.class); int age = annotation.age(); String value = annotation.value(); System.out.println(age+"..."+value); System.out.println(annotation); } //使用自定义注解时需要给属性赋值 @Myinter1(value = "za",age = 30) void show(){} @Myiter2(name = "s") void test(){} @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @interface Myinter1{ String value(); int age () default 20 ; } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @interface Myiter2{ String name(); }
正则表达式就是字符串,只不过是特定规则的字符串
boolean str.matches(String reg) //判断此字符串是否符合这个正则表达式,如果符合返回true,否则是false
String str.replaceAll(String reg,String replacement) //从头开始,依次读取字符,查看是否符合规则,只要符合就替换
String[] str.split(String reg) //从头开始,依次读取字符,查看是否符合规则,只要符合就切割
//字符 x 字符 x \\ 反斜线字符 \0n 带有八进制值 0 的字符 n (0 <= n <= 7) \0nn 带有八进制值 0 的字符 nn (0 <= n <= 7) \0mnn 带有八进制值 0 的字符 mnn(0 <= m <= 3、0 <= n <= 7) \xhh 带有十六进制值 0x 的字符 hh \uhhhh 带有十六进制值 0x 的字符 hhhh \t 制表符 ('\u0009') \n 新行(换行)符 ('\u000A') \r 回车符 ('\u000D') \f 换页符 ('\u000C') \a 报警 (bell) 符 ('\u0007') \e 转义符 ('\u001B') \cx 对应于 x 的控制符
//字符类 [abc] a、b 或 c(简单类) [^abc] 任何字符,除了 a、b 或 c(否定) [a-zA-Z] a 到 z 或 A 到 Z,两头的字母包括在内(范围) //注意:一对中括号代表一个字符,上边中的abc...仅仅是举例子,实际可以换有效字符
. 任何字符(与行结束符可能匹配也可能不匹配) \d 数字:[0-9] \D 非数字: [^0-9] \s 空白字符:[ \t\n\x0B\f\r] \S 非空白字符:[^\s] \w 单词字符:[a-zA-Z_0-9] \W 非单词字符:[^\w]
//边界匹配器 ^ 行的开头 $ 行的结尾 \b 单词边界 \B 非单词边界 \A 输入的开头 \G 上一个匹配的结尾 \Z 输入的结尾,仅用于最后的结束符(如果有的话) \z 输入的结尾
X? X,一次或一次也没有 X* X,零次或多次 X+ X,一次或多次 X{n} X,恰好 n 次 X{n,} X,至少 n 次 X{n,m} X,至少 n 次,但是不超过 m 次
一个常规类,理论上可以创建n个对象,没有上限(不考虑内存)。
目标:
实现一个类无论怎么使用,对象个数永远是那个。
要保障对象在内存中的唯一性。
步骤:
1.构造方法私有化
2.在类中创建一个该类对象
3.定义方法,返回该类对象
//饿汉式 class Single { //因为不想外界创建对象,所有私有化构造方法 private Single(){} //内部提前创建对象 // private不希望外界可以创建对象, // static因为下面的方法是静态的,所以这个也得是静态 // final为了使这个类就一个对象,每次调用都是这个,所以final修饰,锁定这个对象的引用地址 private final static Single s = new Single(); //定义方法返回对象,不能创建对象所有让这个方法Static修饰,直接使用类名调用 public static Single getInstance(){ return s ; } }
特点:类一加载,就创建了该类的对象。
弊端: 对象有可能不使用,因此可能会有空间浪费。
好处:多线程模式下,没有线程安全问题。
//懒汉式 class Single{ //1,私有化构造方法 private Single(){ } //2.创建对象引用 private static Single s = null; //3.定义方法,返回该类对象 public static Single getInstance(){ if(s == null){ synchronized (Single.class) { //t1 t2 if (s == null) s = new Single(); } } return s; } }
特点:类加载时,不会创建对象,调用getInstance方法时才会创建对象,(延时加载).
好处:因此这种方式不会有空间浪费。
弊端:多线程模式下,可能会有线程安全问题
public class Demo4 { public static void main(String[] args) { /*Single s1 = Single.getInstance(); Single s2 = Single.getInstance(); System.out.println(s1 == s2); //比较地址值*/ MyRun my = new MyRun(); new Thread(my).start(); new Thread(my).start(); } } class MyRun implements Runnable{ @Override public void run() { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Single.getInstance()); } } //懒汉式 class Single{ //1,私有化构造方法 private Single(){ } //2.创建对象引用 private static Single s = null; //3.定义方法,返回该类对象 public static Single getInstance(){ if(s == null){ //双重判断提高效率 synchronized (Single.class) { //t1 t2 if (s == null) s = new Single(); } } return s; } }