201871010116-祁英红《面向对象程序设计(java)》第八周学习总结
项目 |
内容 |
《面向对象程序设计(java)》 |
https://home.cnblogs.com/u/nwnu-daizh/ |
这个作业的要求在哪里 |
https://www.cnblogs.com/nwnu-daizh/p/11703678.html |
作业学习目标 |
|
随笔博文正文内容包括:
第一部分:总结第六章理论知识(30分)
一、接口:
(1)接口不是类,而是对类的一组需求描述,这些类要遵从接口描述的统一格式进行定义。如果类遵从某个特定接口,那么就履行这项服务。
(2)Java不支持多继承性,即一个子类只能有一个父类;单继承使得java简单,易于管理,但如果要克服单继承性的缺点就要使用接口技术,是一个类可以实现多个接口,用关键字interface关键字来定义一个接口。
(3)接口声明:interface 接口名; 接口体:包括常量定义和方法定义,方法只允许声明不允许实现。
(4)接口使用:class A implements print,add 或者 class A extends A1 implements print,add
(5)接口中的所有方法自动地属于public,因此,在接口中声明方法时,不必提供关键字public。
(6)接口不能含有实例域,提供实例域和方法实现的任务应该由实现接口地那个类来完成,为了让类实现一个接口:1)将类声明为实现给定的接口。2)对接口中的所有方法进行定义。
(8)当某个类使用接口的时候,必须给出所有方法的实现,方法的类型、参数一定要和接口的一致;接口的方法默认为public abstract,故类在实现时一定不能漏写public关键字;接口常量默认关键字为public static。
(9)int compareTo(T other)
用这个对象与other进行比较,如果这个对象小于other则返回负值,如果相等则返回0,否则返回正值。
static void sort(Object[ ] a)
使用mergesort算法对数组a中的元素进行排序。要求数组中的元素必须属于实现了Comparable接口的类,并且元素之间必须是可比较的。
static int compare(int x,int y)7
如果x<y返回一个一个负整数,如果x和y相等,则返回0,否则返回一个负整数。
static int compare(double x,double y)1.4
如果x<y返回一个负数,如果x和y相等则返回一个0,否则返回一个负数。
(10)接口不是类,不能使用new运算符实例化一个接口,x=new Comparable(...); //ERROR
不能构造接口的对象,但能声明接口的变量,接口变量必须引用实现了接口的类对象,可以使用instance检查一个对象是否实现了某个特定的接口。
(11)因为接口中只含有public static final 常量和public abstract方法,故在写接口的时候可以省略这些关键字。
(12)如果接口的返回类型不是void,那么实现方法体的时候,至少要有一个return语句;如果接口的返回类型是void,可以除了大括号之外可以没有任何语句。
(13)Java提供的接口都在相应的包中,可以通过引入包使用相应的接口;也可以自定义接口,一个源文件就是由类和接口来组成的。
(14)类实现的接口的方法以及接口中的常量可以通过类的对象进行调用,常量也可以通过类名和接口名进行调用。
(15)接口声明的时候,如果加上关键字public,那么接口可以被任一个类进行调用,如果没有public则为友好型接口,只能被同一个包内的类进行调用。
(16)如果父类使用某个接口,那么子类也就使用了接口,不用再使用implements。
(17)接口可以通过extends继承接口。
(18)如果一个类声明实现一个接口但没有实现接口的所有方法,那么这个类一定得是abstract类。
(19)静态方法:从Java SE 8开始,允许在接口中增加静态方法,并给静态方法提供方法体实现,该静态方法只能通过接口名.静态方法
来调用。实现语法只要在方法前面加static关键字即可,这理论上讲是可以的,但这有违于接口作为抽象规范的初衷。静态方法只能被具体实现类继承,不能在实现类中重写。
(20)默认方法:可以为接口方法提供一个默认方法体实现,在方法前加default修饰符即可,这样子类无需重写这个方法也能得到一个接口的默认实现。默认方法也可以被具体实现类重写。在实现类中调用默认方法要使用接口名.super.默认方法来调用。
(21)解决默认方法的冲突:
如果先在一个接口中将一个方法定义为默认方法,然后又在超类或另一个接口中定义了同样的方法,会发生冲突。解决冲突规则如下:
- 超类和接口冲突。如果超类提供了一个具体方法,那么根据超类优先原则,同名而且有相同参数类型的默认方法会被忽略。
- 多接口之间冲突。如果一个实现类实现了多个接口,一个接口提供了一个默认方法,另一个接口提供了一个同名而且参数类型(不论是否是默认参数)相同的方法,此时就发生了接口冲突,必须在实现类中重写这个方法来解决冲突。
(22)解决重名常量的方法:
1. 超类和接口冲突。如果一个类继承了一个超类和实现了若干接口,此时不像默认方法冲突一样有超类优先原则。只能通过在实现类中覆盖该常量来解决冲突。
2. 多接口之间冲突。如果一个类实现了多个接口,而这些接口又有重名常量,此时会发生冲突。必须用接口名.常量
的方式来精确指明要使用的常量。
(23)Comparator接口:Comparator接口意为"比较器"接口,是一个泛型接口,可用于自定义排序规则和大小比较等。要进行自定义排序,Arrays.sort方法有一个重载版本,需要提供一个数组和一个比较器作为参数。
(24)对象克隆:原变量和副本都会指向同一个对象,这说明,任何一个变量的改变都会影响到另一个变量。如果有一个对象original,希望创建一个对象copy使得其初始状态与original相同,但是之后它们各自回有自己不同的状态,这种情况下就可以使用克隆。clone() 方法并不是 Cloneable 接口的方法,而是 Object 的一个 protected 方法。Cloneable 接口只是规定,如果一个类没有实现 Cloneable 接口又调用了 clone() 方法,就会抛出 CloneNotSupportedException。
(25)接口和抽象类:
区别:
1.接口所有的变量必须是public static final;抽象类的变量无限制
2.接口没有构造方法,不能用new操作符实例化;抽象类有构造方法,由子类通过构造方法链调用,不能用new操作符实例化
3.接口所有方法必须是公共抽象实例方法(Java SE 8开始允许定义静态方法),抽象类无限制
4.一个类只可以继承一个父类,但可以实现多个接口
5.所有的类有一个共同的根Object类,接口没有共同的根
6.抽象类和子类的关系应该是强的“是一种”关系(strong is-a relationship),而接口和子类的关系是弱的"是一种"关系(weak is-a relationship)。接口比抽象类更灵活,因为实现接口的子类只需要具有统一的行为即可,不需要都属于同一个类型的类。
二、lambda表达式:
(1)lambda表达式是一个可传递的代码块,可以在以后执行一次或多次
(2)lambda表达式的语法:
包含三个部分
-
一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数
-
一个箭头符号:->
-
方法体,可以是表达式和代码块,方法体函数式接口里面方法的实现,如果是代码块,则必须用{}来包裹起来,且需要一个return 返回值,但有个例外,若函数式接口里面方法返回值是void,则无需{ }
(3)函数式接口:对于只有一个抽象方法的接口,需要这种接口的对象时,就可以提供一个lambda表达式,这种接口称为函数式接口。
(4)方法引用:其实是lambda表达式的一个简化写法,所引用的方法其实是lambda表达式的方法体实现,语法也很简单,左边是容器(可以是类名,实例名),中间是"::",右边是相应的方法名。
一般方法的引用格式是
-
如果是静态方法,则是ClassName::methodName。如 Object ::equals
-
如果是实例方法,则是Instance::methodName。如Object obj=new Object();obj::equals;
-
构造函数.则是ClassName::new
(5)构造器引用:构造器引用与方法引用类似,只不过方法名为new。例如Employee::new
是Employee构造器的一个引用。至于是哪一个构造器取决于上下文,比如Function<Integer,Employee> func1 = Employee :: new;
就相当于Function<Integer,Employee> func = x -> new Employee(x);
数组类型也有构造器引用,如int[]::new
等价于lambda表达式x -> new int[x]
(6)处理lambda表达式:
我们之前提到,lambda表达式的重点是延迟执行,之所以希望以后再执行代码,有很多原因,如:
1. 在一个单独的线程中运行代码
2. 多次运行代码
3. 在算法的恰当位置运行代码(例如,排序中的比较操作)
4. 发生某种情况时执行代码(如,点击了一个按钮、数据到达等)
5. 只在必要时才运行代码
下面是常用的函数式接口和基本类型的函数式接口:
(7)为什么需要lambda表达式:
主要有三个原因:
1. 更加紧凑的代码
2. 修改方法的能力
3. 更好地支持多核处理
三、内部类:
(1)内部类,或者称为嵌套类,是一个定义在另一个类范围中的类。一个内部类可以如常规类一样使用。通常,在一个类只被它的外部类所使用的时候,才将它定义为内部类,内部类机制主要用于设计具有互相协作关系的类集合。
(2)使用内部类的好处:
1.内部类可以很好地实现隐藏:一般的非内部类,是不允许有 private 与protected权限的,但内部类可以。
2.成员内部类拥有外围类的所有元素的访问权限:内部类可以访问包含它的外部类的所有数据域(包括私有数据域)和方法,没有必要将外部类对象的引用传递给内部类的构造方法,内部类有一个指向外部类对象的隐式引用,如果显式写出,外部类的引用是OuterClass.this。
3.可以间接实现多重继承:比如在A类中定义两个内部类innerClass1和innerClass2分别继承B类和C类,则A类就具有了B类和C类的属性和方法,间接实现了多重继承。
4.减小了类文件编译后的产生的字节码文件的大小。
(3)内部类具有一下特征:
- 一个内部类被编译成一个名为
OuterClassName$InnerClassName
的类。例如,一个定义在Test类中的成员内部类A被编译成Test$A.class
。 - 内部类对象通常在外部类中创建,但是你也可以从另外一个类中来创建一个内部类的对象。如果是成员内部类,你必须先创建一个外部类的实例,然后使用下面的语法创建一个内部类对象:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
如果是静态内部类的,使用下面语法来创建一个内部类对象:OuterClass.InnerClass innerObject = new OuterClass.InnerClass();
(4)局部内部类:可以把内部类定义在一个方法中,称为局部内部类,也叫方法内部类。局部内部类就像是方法里面的一个局部变量一样,不能有public、protected、private以及static修饰符。它的作用域被限定在声明这个局部类的块中。局部类有一个优势,即对外部世界完全隐藏起来。即使外部类中的其他代码也不能访问它。除了其所在的方法之外,没有任何方法知道该局部类的存在。局部内部类只能访问被final修饰的局部变量。
(5)匿名内部类:有时我们在程序中对一个类只使用一次,此时就可以把类的定义和实例化对象整合在一起,来简化对于抽象类和接口实现的操作,这就是匿名内部类。
(6)静态内部类:有时候,使用内部类只是为了把一个类隐藏在另外一个类的内部,并不需要内部类引用外围类的元素。为此,可以为内部类加上static关键字声明为静态内部类。
静态内部类不持有外部类的引用,只能访问外部类的静态成员变量和方法,而不能访问外部类的非静态成员属性和非静态方法,如果要调用和访问,必须实例化外部类对象。当静态内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的
是静态内部类的成员。如果要访问外部类的非静态同名成员,不能再使用外部类.this.成员
的形式,而是要实例化外部类对象。如果要访问外部类的静态同名成员,可以通过外部类.成员
的方式来访问。
与常规内部类不同,静态内部类可以有静态变量和静态方法。可以通过外部类.内部类.静态成员
方式来访问。
四、代理:
(1)利用代理可以在运行时创建一个实现了一组给定接口的新类。
(2)创建代理对象:
要想创建一个代理对象,需要使用Proxy类的newProxyInstance方法,这个方法有三个参数:
1. 一个类加载器(class loader)
2. 一个class对象数组
3. 一个调用处理器
(3)代理类的特性:
1. 所有的代理类都扩展于Proxy类。
2. 所有的代理类都覆盖了Object类中的方法toString、equals和hashCode。
3. 没有顶定义代理类的名字,Sun虚拟机中的Proxy类将生成一个以字符串$Proxy开头的类名。
4. 代理类一定是public和final。
第二部分:实验部分
实验1:测试程序1(5分)
package interfaces; import java.util.*; /** * This program demonstrates the use of the Comparable interface. * @version 1.30 2004-02-27 * @author Cay Horstmann */ public class EmployeeSortTest //用EmployeeTest关联Employee { public static void main(String[] args) { Employee[] staff = new Employee[3]; //定义数组 staff[0] = new Employee("Harry Hacker", 35000); staff[1] = new Employee("Carl Cracker", 75000); staff[2] = new Employee("Tony Tester", 38000); Arrays.sort(staff); //进行排序 // print out information about all Employee objects for (Employee e : staff) System.out.println("name=" + e.getName() + ",salary=" + e.getSalary()); } }
package interfaces; public class Employee implements Comparable<Employee> //为泛型数组Comparable接口提供一个类型参数 { private String name; private double salary; public Employee(String name, double salary) { this.name = name; this.salary = salary; } public String getName() { return name; } public double getSalary() { return salary; } public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; } /** * Compares employees by salary * @param other another Employee object * @return a negative value if this employee has a lower salary than * otherObject, 0 if the salaries are the same, a positive value otherwise */ public int compareTo(Employee other) //用Employee对象与other进行比较 { return Double.compare(salary, other.salary); //使用静态Double.compare方法 } }
程序运行结果如下:
接口中的所有方法自动地属于pubic,在接口中声明方法时,不必提供关键字public。
为了让类实现一个接口,需要:
(1)将类声明为实现给定的接口,使用关键字implements.
(2)对接口中的所有方法进行定义。
comparable接口:类对象之间比较“大小”往往是很有用的操作,比如让对象数组排序时,就需要依赖比较操作。对于不同的类有不同的语义。如Student类,比较2个学生对象可以比较他们的score分数来评判。
Java不支持预算符重载,我们通过实现Comparable接口达到相同的目的。当类实现了Comparable接口,则认为这个类的对象之间是可比较的。
int compareTo(T other)
用这个对象与other进行比较,如果这个对象小于other则返回负值,如果相等则返回0,否则返回正值。
实验1:测试程序2(5分)
程序代码如下:
interface A { double g=9.8; void show( ); } class C implements A { public void show( ) {System.out.println("g="+g);} } class InterfaceTest { public static void main(String[ ] args) { A a=new C( ); a.show( ); System.out.println("g="+C.g); } }
运行结果如下:
实验1:测试程序3(5分)
程序代码如下:
package timer; /** @version 1.02 2017-12-14 @author Cay Horstmann */ import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import javax.swing.Timer; public class TimerTest { public static void main(String[] args) { ActionListener listener = new TimePrinter(); //构造ActionListener listener类的一个对象,并将它传递给Timer构造器 // construct a timer that calls the listener // once every 10 seconds Timer t = new Timer(1000, listener); t.start(); //启动定时器 // keep program running until the user selects "OK" JOptionPane.showMessageDialog(null, "Quit program?"); System.exit(0); } } //定义一个实现ActionListener接口的类 class TimePrinter implements ActionListener //定时器需要知道调用的方法,并要求传递的对象所属的类实现了java。awt.event包中的ActionListener接口 { public void actionPerformed(ActionEvent event) //当到达指定的时间间隔时,定时器就调用actionPerformed方法 { System.out.println("At the tone, the time is " + new Date()); Toolkit.getDefaultToolkit().beep(); } }
程序运行结果如下:
回调设计模式:
核心总结:
1.接口作为方法参数,实际传入的是具体的实现类对象
2.A类让B类做一件事情,B做完后告诉A
实验1:测试程序4(5分)
程序代码如下:
package clone; /** * This program demonstrates cloning. * @version 1.11 2018-03-16 * @author Cay Horstmann */ public class CloneTest { public static void main(String[] args) throws CloneNotSupportedException { var original = new Employee("John Q. Public", 50000); original.setHireDay(2000, 1, 1); Employee copy = original.clone(); copy.raiseSalary(10); copy.setHireDay(2002, 12, 31); System.out.println("original=" + original); System.out.println("copy=" + copy); } }
package clone; import java.util.Date; import java.util.GregorianCalendar; public class Employee implements Cloneable //将克隆定义为public,调用super.clone() { private String name; private double salary; private Date hireDay; public Employee(String name, double salary) { this.name = name; this.salary = salary; hireDay = new Date(); } //创建深拷贝的clone方法 public Employee clone() throws CloneNotSupportedException //声明异常 { // call Object.clone() 调用对象克隆 Employee cloned = (Employee) super.clone(); // clone mutable fields 克隆易变字段 cloned.hireDay = (Date) hireDay.clone(); return cloned; } /** * Set the hire day to a given date. * @param year the year of the hire day * @param month the month of the hire day * @param day the day of the hire day */ public void setHireDay(int year, int month, int day) { Date newHireDay = new GregorianCalendar(year, month - 1, day).getTime(); // example of instance field mutation hireDay.setTime(newHireDay.getTime()); } public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; } public String toString() { return "Employee[name=" + name + ",salary=" + salary + ",hireDay=" + hireDay + "]"; } }
程序运行结果如下:
1. 对象克隆实现技术:克隆这个词大家并不陌生,实质就是拷贝对象,形成一个对象的副本。克隆对象就是对已有的一个对象进行拷贝。
进行克隆的目的(意义):被克隆和克隆对象之间完全复制、相互之间没有影响的目的。
为什么要使用克隆对象:当我们new一个对象之后是要对该对象进行初始化的,不然这个对象是空的没有内容。而使用克隆,则会得到一个原对象以及原对象里面包含的内容。例如,你有一个User对象,里面的包含了相关的属性。此时你想要修改里面的某一属性,但又不想破坏原对象里面的数据,此时就可以克隆User这个对象,然后在克隆的这个User对象上进行修改操作。除此,如果你在操作完之后判断一下属性是否更改成功,则使用克隆的对象和原对象做一下对比即可。
2.浅拷贝和深拷贝的差别:浅拷贝是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象。深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。例如:对象A1中包含对B1的引用,B1中包含对C1的引用。浅拷贝A1得到A2,A2 中依然包含对B1的引用,B1中依然包含对C1的引用。深拷贝则是对浅拷贝的递归,深拷贝A1得到A2,A2中包含对B2(B1的copy)的引用,B2 中包含对C2(C1的copy)的引用。
若不对clone()方法进行改写,则调用此方法得到的对象即为浅拷贝。
实验2:(10分)
程序代码如下:
package lambda; import java.util.*; import javax.swing.*; import javax.swing.Timer; /** * This program demonstrates the use of lambda expressions. * @version 1.0 2015-05-12 * @author Cay Horstmann */ public class LambdaTest { public static void main(String[] args) { var planets = new String[] { "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune" }; System.out.println(Arrays.toString(planets)); System.out.println("Sorted in dictionary order:"); Arrays.sort(planets); //调用Arrays类的sort方法 System.out.println(Arrays.toString(planets)); System.out.println("Sorted by length:"); Arrays.sort(planets, (first, second) -> first.length() - second.length()); //lambda表达式 System.out.println(Arrays.toString(planets)); var timer = new Timer(1000, event -> System.out.println("The time is " + new Date())); timer.start(); // keep program running until user selects "OK" JOptionPane.showMessageDialog(null, "Quit program?"); //窗口显示信息"Quit program?" System.exit(0); } }
程序运行结果如下:
lambda表达式的优缺点:
优点:
1. 简洁。
2. 非常容易并行计算。
3. 可能代表未来的编程趋势。
4. 结合 hashmap 的 computeIfAbsent 方法,递归运算非常快。java有针对递归的专门优化。
缺点:
1. 若不用并行计算,很多时候计算速度没有比传统的 for 循环快。(并行计算有时需要预热才显示出效率优势,并行计算目前对 Collection 类型支持的好,对其他类型支持的一般)
2. 不容易调试。
3. 若其他程序员没有学过 lambda 表达式,代码不容易让其他语言的程序员看懂。
4. 在 lambda 语句中强制类型转换貌似不方便,一定要搞清楚到底是 map 还是 mapToDouble 还是 mapToInt
实验3:编程练习(25分)
程序代码如下:
package ID; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; import java.util.Scanner; import java.util.Collections;//对集合进行排序、查找、修改等; public class Main { private static ArrayList<Citizen> citizenlist; public static void main(String[] args) { citizenlist = new ArrayList<>(); Scanner scanner = new Scanner(System.in); File file = new File("D://身份证号.txt"); //异常捕获 try { FileInputStream fis = new FileInputStream(file); BufferedReader in = new BufferedReader(new InputStreamReader(fis)); String temp = null; while ((temp = in.readLine()) != null) { Scanner linescanner = new Scanner(temp); linescanner.useDelimiter(" "); String name = linescanner.next(); String id = linescanner.next(); String sex = linescanner.next(); String age = linescanner.next(); String birthplace = linescanner.nextLine(); Citizen citizen = new Citizen(); citizen.setName(name); citizen.setId(id); citizen.setSex(sex); // 将字符串转换成10进制数 int ag = Integer.parseInt(age); citizen.setage(ag); citizen.setBirthplace(birthplace); citizenlist.add(citizen); } } catch (FileNotFoundException e) { System.out.println("信息文件找不到"); e.printStackTrace(); } catch (IOException e) { System.out.println("信息文件读取错误"); e.printStackTrace(); } boolean isTrue = true; while (isTrue) { System.out.println("1.按姓名字典序输出人员信息"); System.out.println("2.查询最大年龄的人员信息、查询最小年龄人员信息"); System.out.println("3.查询人员中是否有你的同乡"); System.out.println("4.输入你的年龄,查询文件中年龄与你最近人的姓名、身份证号、年龄、性别和出生地"); System.out.println("5.退出"); int nextInt = scanner.nextInt(); switch (nextInt) { case 1: Collections.sort(citizenlist); System.out.println(citizenlist.toString()); break; case 2: int max = 0, min = 100; int m, k1 = 0, k2 = 0; for (int i = 1; i < citizenlist.size(); i++) { m = citizenlist.get(i).getage(); if (m > max) { max = m; k1 = i; } if (m < min) { min = m; k2 = i; } } System.out.println("年龄最大:" + citizenlist.get(k1)); System.out.println("年龄最小:" + citizenlist.get(k2)); break; case 3: System.out.println("出生地:"); String find = scanner.next(); String place = find.substring(0, 3); for (int i = 0; i < citizenlist.size(); i++) { if (citizenlist.get(i).getBirthplace().substring(1, 4).equals(place)) System.out.println("出生地" + citizenlist.get(i)); } break; case 4: System.out.println("年龄:"); int yourage = scanner.nextInt(); int near = peer(yourage); int j = yourage - citizenlist.get(near).getage(); System.out.println("" + citizenlist.get(near)); break; case 5: isTrue = false; System.out.println("程序已退出!"); break; default: System.out.println("输入有误"); } } } public static int peer(int age) { int flag = 0; int min = 53, j = 0; for (int i = 0; i < citizenlist.size(); i++) { j = citizenlist.get(i).getage() - age; if (j < 0) j = -j; if (j < min) { min = j; flag = i; } } return flag; } }
package ID; public class Citizen implements Comparable<Citizen> { private String name; private String id; private String sex; private int age; private String birthplace; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getage() { return age; } public void setage(int age) { this.age = age; } public String getBirthplace() { return birthplace; } public void setBirthplace(String birthplace) { this.birthplace = birthplace; } public int compareTo(Citizen other) { return this.name.compareTo(other.getName()); } public String toString() { return name + "\t" + sex + "\t" + age + "\t" + id + "\t" + birthplace + "\n"; } }
程序运行结果如下:
实验总结:(10分)
通过这周的实验学习,初步掌握了接口的一些简单知识:接口本身就是一个特殊的类;接口不能实例化(不能new,但是可是使用多态去进行实例化);接口的子类可以是抽象类,也可以是具体类(重写接口类里的所有方法);接口的成员变量(默认是常量):成员特点:只能是常量,并且是静态,因为默认情况下接口成员变量的修饰符是:public static final;构造方法:接口没有构造方法;成员方法:只能是抽象方法,其中默认修饰符是:public abstract ; 注意:抽象方法中不能有主题;接口不能创建对象;接口没有构造方法;因为接口是提供给类使用,当非抽象类去实现一个接口时,必须把接口中所有方法都实现。还了解了lambda表达式的用法及优缺点,为什么要使用lambda表达式。