多态分为对象多态和行为多态【其实就是一种现象】
对象多态——意思就是,一个变量,它可以指向不同的对象【在继承的情况下,父对象可以指向一个子类型的变量】
行为多态——意思就是,一个父类型的变量,可以根据其实际指向的变量类型来判断运行哪种类型的方法【也即编译时看左边,运行时看右边】
为了减少重复代码的编写
建议用final关键字修饰模板方法
接口里只能有成员变量(默认为常量)和成员方法(抽象方法)
一个类可以实现多个接口;与继承不同【extends】,只能继承一个
修饰符 class 实现类名 implements 接口1,接口2,接口3,...{
}
成员变量、内部类、构造器、方法、代码块
创建格式【先创建外部类的对象再创建内部类的对象】
由外部类自己持有
创建格式【直接用外部类.内部类来创建对象】
静态内部类只能访问外部类的静态成员【道理很简单,因为静态类可以不创建对象就访问,如果静态内部类可以访问外部类的实例成员变量,则会报错】
所谓匿名内部类的意思就是没有名字
创建格式
该类会创建一个子类对象,也即Java会自己创建一个【类或接口】的子类(用extends)。
适用场景
当一个方法的参数是一个接口类对象时,如果要调用该方法,则需要用匿名内部类来创建一个接口对象。
注:
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的参数列表,有兼容的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求,不能根据返回类型进行区分。
包装类和基本数据类型可以自动装箱和自动拆箱
StringBuilder是线程不安全的,StringBuffer是线程安全的
注意:只能用于函数式接口,也即该接口中只有一个函数
类名::静态方法
使用场景:
如果某个Lambda表达式里只是调用一个静态方法,并且前后参数的形式一致,就可以用静态方法引用
package com.lidiang.reference1;
import java.util.Arrays;
import java.util.Comparator;
public class StacticReference {
public static void main(String[] args) {
Student[] students = new Student[5];
students[0] = new Student("A",88);
students[1] = new Student("Lily",12);
students[2] = new Student("Alice",54);
students[3] = new Student("God",108);
students[4] = new Student("Bob",68);
// 1.lambda表达式的标准写法
// Arrays.sort(students, new Comparator<Student>() {
// @Override
// public int compare(Student o1, Student o2) {
// return o1.getAge()-o2.getAge();
// }
// });
// 2.简写,当参数列表与重写函数的参数列表相同时,可以省略到如下形式
// Arrays.sort(students, (o1, o2)-> {
// return o1.getAge()-o2.getAge();
// }
// );
// 3.再简写,此时还可以直接把return和大括号也省略了
// Arrays.sort(students, (o1, o2)-> o1.getAge()-o2.getAge());
// 4.静态方法,这里省略了return和大括号,且调用的是静态方法
Arrays.sort(students, (o1, o2)-> CompareStatic.compare(o1,o2));
// 5.静态方法引用
Arrays.sort(students, CompareStatic::compare);
System.out.println(Arrays.toString(students));
}
}
其中静态方法所在的类描述如下:
package com.lidiang.reference1;
public class CompareStatic {
public static int compare(Student o1,Student o2){
return o1.getAge()-o2.getAge();
}
}
学生类如下:
package com.lidiang.reference1;
public class Student {
String name;
int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
类名::实例方法
适用场景:
如果某个Lambda表达式里只是调用一个实例方法,并且前后参数的形式一致,就可以用实例方法引用
package com.lidiang.reference1;
import java.util.Arrays;
import java.util.Comparator;
public class StacticReference {
public static void main(String[] args) {
Student[] students = new Student[5];
students[0] = new Student("A",88);
students[1] = new Student("Lily",12);
students[2] = new Student("Alice",54);
students[3] = new Student("God",108);
students[4] = new Student("Bob",68);
// 1.lambda表达式的标准写法
// Arrays.sort(students, new Comparator<Student>() {
// @Override
// public int compare(Student o1, Student o2) {
// return o2.getAge()-o1.getAge();
// }
// });
// 创建一个比较对象
CompareStatic cp = new CompareStatic();
// 2.调用该对象的实例方法进行sort
// Arrays.sort(students,(o1,o2)->cp.comparedes(o1,o2));
// 3.实例方法引用
Arrays.sort(students,cp::comparedes);
System.out.println(Arrays.toString(students));
}
此时的实例方法如下:
package com.lidiang.reference1;
public class CompareStatic {
// public static int compare(Student o1,Student o2){
// return o1.getAge()-o2.getAge();
// }
public int comparedes(Student o1,Student o2){
return o2.getAge()-o1.getAge();
}
}
不太懂,感觉用的不多
类名::new
适用场景:
如果某个Lambda表达式里只是在创建对象,并且前后参数情况一致,就可以使用构造器引用
package com.lidiang.reference2;
import com.lidiang.reference1.Student;
public class NimingTest {
public static void main(String[] args) {
// 1.创建一个匿名内部类
// CreateStudent cs = new CreateStudent() {
// @Override
// public Student Create(String name, int age) {
// return new Student(name,age);
// }
// };
// 2.简化后
// CreateStudent cs =(name,age)->new Student(name,age);
// 3.构造器引用;注意,这里的类::new中的类指的是被创建的类名,在这里指的是Student
CreateStudent cs =Student::new;
Student cc = cs.Create("小明",56);
System.out.println(cc);
}
}
// 声明一个创建对象的接口
interface CreateStudent{
Student Create(String name,int age);
}
String matches(String regex)
其中regex的书写规则如下:
该功能利用正则表达式regex,模式化的对字符串文本进行提取信息。
主要有以下步骤:
a. 编写正则表达式regex
b. 确定待提取文本string
c. 创建Pattern对象
d. 创建Matcher对象
e. 用matcher.find进行提取,用matcher.group获取提取出的信息
例子如下:
package com.lidiang.zhengze;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Find {
public static void main(String[] args) {
// 待查找的字符串
String string = "移动号码:18985686359" +
"QQ: 7876959412@qq.com 热线电话:400-610-1360 4006101360 400610-1360";
// 带匹配的正则式
String regex = "(1[3-9]\\d{2,9})|(\\w{2,}@\\w{2,7}(\\.\\w{3,}){1,2})|(4\\d{2,5}(-?\\d{3,6}){2})";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(string);
while(matcher.find()){
System.out.println(matcher.group());
}
// matchphone();
}
// 用正则式匹配字符串,判断字符串是否正确
static void matchphone() {
while (true) {
System.out.println("请输入您的电话号码:");
Scanner sc = new Scanner(System.in);
String string = sc.next();
boolean out = string.matches("1[3-9]\\d{2,9}");
if (out) {
System.out.println("号码正确~~");
} else {
System.out.println("号码错误~~");
}
}
}
}
该功能主要利用String的实例方法replaceALL
例子如下:
package com.lidiang.zhengze;
public class Replace {
public static void main(String[] args) {
// 用正则表达式来匹配字段并替换
String st1 = "留学生sjisds4445女jisjisjd5889889小兰sjskdjas华中科技大学硕士";
System.out.println(st1.replaceAll("\\w+", ","));
// 用正则表达式去除多余的字符
String st2 = "我我我我我我爱爱爱爱爱爱爱爱学学学学学学学学学学习习";
System.out.println(st2.replaceAll("(.)\\1+", "$1"));
}
}