实验六 接口的定义与使用
实验时间 2018-10-18
基础知识:
一 接口:用interface声明,是抽象方法和常量值定义的集 合。从本质上讲,接口是一种特殊的抽象类。
(1)在Java程序设计语言中,接口不是类,而是对类 的一组需求描述,由常量和一组抽象方法组成。 接口中不包括变量和有具体实现的方法。
(2)接口体中包含常量定义和方法定义,接口中只进 行方法的声明,不提供方法的实现。
(3)通常接口的名字以able或ible结尾;
(4)接口中的所有常量必须是public static final,方法必须是public abstract,这是 系统默认的,不管你在定义接口时,写不写 修饰符都是一样的.
(5)接口的实现:一个类使用了某个接口,那么这个类必须实现该 接口的所有方法,即为这些方法提供方法体。一个类可以实现多个接口,接口间应该用逗号分 隔开。
(6)接口的使用:接口不能构造接口对象,但可以声明接口变量以指向一个实现了该接口的类对象。
(7)可以用instanceof检查对象是否实现了某个接口。
(8)抽象类:用abstract来声明,没有具体实例对象的类,不 能用new来创建对象。
二 接口示例
(1)回调(callback):一种程序设计模式,在这种模 式中,可指出某个特定事件发生时程序应该采取 的动作。
(2)Comparator接口所在包: java.util.*
(3)Object类的Clone方法:当拷贝一个对象变量时,原始变量与拷贝变量 引用同一个对象。这样,改变一个变量所引用 的对象会对另一个变量产生影响。
(4)如果要创建一个对象新的copy,它的最初状态与 original一样,但以后可以各自改变状态,就需 要使用Object类的clone方法。
(5)Object.clone()方法返回一个Object对象。必须进行强 制类型转换才能得到需要的类型。
(6)浅层拷贝与深层拷贝
(7)Java中对象克隆的实现:在子类中实现Cloneable接口。
(8)在子类的clone方法中,调用super.clone()。
三 lambda表达式
(1)Java Lambda 表达式是 Java 8 引入的一个新的功能,主 要用途是提供一个函数化的语法来简化编码。
(2)Lambda 表达式的语法基本结构 (arguments) -> body
(3)有如下几种情况: 1、参数类型可推导时,不需要指定类型,如 (a) -> System.out.println(a)
2、 只有一个参数且类型可推导时,不强制写 (), 如 a -> System.out.println(a)
3、 参数指定类型时,必须有括号,如 (int a) -> System.out.println(a)
4、参数可以为空,如 () -> System.out.println(“hello”)
5、 body 需要用 {} 包含语句,当只有一条语句时 {} 可省略
四 内部类:是定义在一个类内部的类。
(1)使用内部类的原因有以下三个: –内部类方法可以访问该类定义所在的作用域中 的数据,包括私有数据。
–内部类能够隐藏起来,不为同一包中的其他类 所见。
–想要定义一个回调函数且不想编写大量代码时, 使用匿名内部类比较便捷。
(2)内部类可以直接访问外部类的成员,包括 private成员,但是内部类的成员却不能被外部 类直接访问。
(3)内部类并非只能在类内定义,也可以在程序块内 定义局部内部类。
(4)如果构造参数的闭圆括号跟一个开花括号,表明正 在定义的就是匿名内部类。
实验内容
1、实验目的与要求
(1) 掌握接口定义方法;
(2) 掌握实现接口类的定义要求;
(3) 掌握实现了接口类的使用要求;
(4) 掌握程序回调设计模式;
(5) 掌握Comparator接口用法;
(6) 掌握对象浅层拷贝与深层拷贝方法;
(7) 掌握Lambda表达式语法;
(8) 了解内部类的用途及语法要求。
2、实验内容和步骤
实验1: 导入第6章示例程序,测试程序并进行代码注释。
测试程序1:
l 编辑、编译、调试运行阅读教材214页-215页程序6-1、6-2,理解程序并分析程序运行结果;
l 在程序中相关代码处添加新知识的注释。
l 掌握接口的实现用法;
l 掌握内置接口Compareable的用法。
1 package interfaces; 2 3 import java.util.*; 4 5 /** 6 * This program demonstrates the use of the Comparable interface. 7 * @version 1.30 2004-02-27 8 * @author Cay Horstmann 9 */ 10 public class EmployeeSortTest 11 { 12 public static void main(String[] args) 13 { 14 Employee[] staff = new Employee[3]; //emploee对象数组 15 16 staff[0] = new Employee("Harry Hacker", 35000); 17 staff[1] = new Employee("Carl Cracker", 75000); 18 staff[2] = new Employee("Tony Tester", 38000); 19 20 Arrays.sort(staff); //sort为静态方法(排序) 21 22 //输出所有雇员的信息 23 for (Employee e : staff) 24 System.out.println("name=" + e.getName() + ",salary=" + e.getSalary()); 25 } //按工资的多少排序 26 }
1 package interfaces; 2 3 public class Employee implements Comparable<Employee>//employee为用户自定义类,Comparable为接口名,实现了jdk的内置接口 4 { 5 private String name; 6 private double salary; //属性 7 8 public Employee(String name, double salary) 9 { 10 this.name = name; 11 this.salary = salary; 12 } //构造器 13 14 public String getName() 15 { 16 return name; 17 } //访问器 18 19 public double getSalary() 20 { 21 return salary; 22 } //访问器 23 24 public void raiseSalary(double byPercent) 25 { 26 double raise = salary * byPercent / 100; 27 salary += raise; 28 } //完成涨工资的计算 29 30 /** 31 * Compares employees by salary 32 * @param other another Employee object 33 * @return a negative value if this employee has a lower salary than 34 * otherObject, 0 if the salaries are the same, a positive value otherwise 35 */ 36 public int compareTo(Employee other) //comparable接口的compareTo方法,返回一个整型数值 37 { 38 return Double.compare(salary, other.salary); //double包装器的compare方法 39 } 40 }
测试程序2:
l 编辑、编译、调试以下程序,结合程序运行结果理解程序;
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); } } |
测试程序3:
l 在elipse IDE中调试运行教材223页6-3,结合程序运行结果理解程序;
l 26行、36行代码参阅224页,详细内容涉及教材12章。
l 在程序中相关代码处添加新知识的注释。
1 package timer; 2 3 /** 4 @version 1.01 2015-05-12 5 @author Cay Horstmann 6 */ 7 8 import java.awt.*; 9 import java.awt.event.*; 10 import java.util.*; 11 import javax.swing.*; 12 import javax.swing.Timer; 13 // to resolve conflict with java.util.Timer 14 15 public class TimerTest 16 { 17 public static void main(String[] args) 18 { 19 //构造这个类的一个对象,并把它传给timer构造器 20 ActionListener listener = new TimePrinter(); 21 22 // 构造调用侦听器的计时器 23 // 每十秒钟一次 24 Timer t = new Timer(10000, listener); 25 26 t.start();//启动定时器 27 //程序将弹出一个消息对话框 28 JOptionPane.showMessageDialog(null, "Quit program?"); 29 System.exit(0); 30 } 31 } 32 33 class TimePrinter implements ActionListener //类为TimePrinter,接口为ActionListener,此为内置接口,并无需定义 34 { 35 public void actionPerformed(ActionEvent event) //当到达指定的时间间隔时。定时器就调用actionPerformed方法,为抽象方法 36 { 37 System.out.println("At the tone, the time is " + new Date()); 38 Toolkit.getDefaultToolkit().beep();//①通过类名调用静态方法,返回值为toolkit对象②toolkit对象再调用beep方法 39 } 40 }
l 掌握回调程序设计模式;
测试程序4:
l 调试运行教材229页-231页程序6-4、6-5,结合程序运行结果理解程序;
l 在程序中相关代码处添加新知识的注释。
1 package clone; 2 3 import java.util.Date; 4 import java.util.GregorianCalendar; 5 6 public class Employee implements Cloneable 7 { 8 private String name; 9 private double salary; 10 private Date hireDay; //属性 11 12 public Employee(String name, double salary) 13 { 14 this.name = name; 15 this.salary = salary; 16 hireDay = new Date(); 17 } //构造器 18 19 public Employee clone() throws CloneNotSupportedException 20 { 21 // call Object.clone() 22 Employee cloned = (Employee) super.clone(); 23 24 // clone mutable fields 25 cloned.hireDay = (Date) hireDay.clone(); 26 27 return cloned; 28 } //抛出异常 29 30 /** 31 * Set the hire day to a given date. 32 * @param year the year of the hire day 33 * @param month the month of the hire day 34 * @param day the day of the hire day 35 */ 36 public void setHireDay(int year, int month, int day) 37 { 38 Date newHireDay = new GregorianCalendar(year, month - 1, day).getTime(); 39 40 // 实例字段突变示例 41 hireDay.setTime(newHireDay.getTime()); 42 } 43 44 public void raiseSalary(double byPercent) 45 { 46 double raise = salary * byPercent / 100; 47 salary += raise; 48 } //完成涨工资的计算 49 50 public String toString() 51 { 52 return "Employee[name=" + name + ",salary=" + salary + ",hireDay=" + hireDay + "]"; 53 } 54 }
1 package clone; 2 3 /** 4 * This program demonstrates cloning. 5 * @version 1.10 2002-07-01 6 * @author Cay Horstmann 7 */ 8 public class CloneTest 9 { 10 public static void main(String[] args) 11 { 12 try 13 { 14 Employee original = new Employee("John Q. Public", 50000); 15 original.setHireDay(2000, 1, 1); 16 Employee copy = original.clone(); 17 copy.raiseSalary(10); 18 copy.setHireDay(2002, 12, 31); 19 System.out.println("original=" + original); 20 System.out.println("copy=" + copy); 21 } 22 catch (CloneNotSupportedException e) 23 { 24 e.printStackTrace(); //异常处理 25 } 26 } 27 }
l 掌握对象克隆实现技术;
l 掌握浅拷贝和深拷贝的差别。
实验2: 导入第6章示例程序6-6,学习Lambda表达式用法。
l 调试运行教材233页-234页程序6-6,结合程序运行结果理解程序;
l 在程序中相关代码处添加新知识的注释。
l 将27-29行代码与教材223页程序对比,将27-29行代码与此程序对比,体会Lambda表达式的优点。
1 package lambda; 2 3 import java.util.*; 4 5 import javax.swing.*; 6 import javax.swing.Timer; 7 8 /** 9 * This program demonstrates the use of lambda expressions. 10 * @version 1.0 2015-05-12 11 * @author Cay Horstmann 12 */ 13 public class LambdaTest 14 { 15 public static void main(String[] args) 16 { 17 String[] planets = new String[] { "Mercury", "Venus", "Earth", "Mars", 18 "Jupiter", "Saturn", "Uranus", "Neptune" }; 19 System.out.println(Arrays.toString(planets)); 20 System.out.println("Sorted in dictionary order:"); 21 Arrays.sort(planets); //按字典顺序对planets排序 22 System.out.println(Arrays.toString(planets)); 23 System.out.println("Sorted by length:"); 24 Arrays.sort(planets, (first, second) -> first.length() - second.length()); 25 System.out.println(Arrays.toString(planets));//lambda表达式,按字符串长度对planets排序 26 27 Timer t = new Timer(1000, event -> 28 System.out.println("The time is " + new Date())); //lambda表达式 29 t.start(); 30 31 // 保持程序运行直到用户选择ok
32 JOptionPane.showMessageDialog(null, "Quit program?"); 33 System.exit(0); 34 } 35 }
注:以下实验课后完成
实验3: 编程练习
l 编制一个程序,将身份证号.txt 中的信息读入到内存中;
l 按姓名字典序输出人员信息;
l 查询最大年龄的人员信息;
l 查询最小年龄人员信息;
l 输入你的年龄,查询身份证号.txt中年龄与你最近人的姓名、身份证号、年龄、性别和出生地;
l 查询人员中是否有你的同乡。
代码如下
1 package xinxi; 2 3 import java.io.BufferedReader; 4 import java.io.File; 5 import java.io.FileInputStream; 6 import java.io.FileNotFoundException; 7 import java.io.IOException; 8 import java.io.InputStreamReader; 9 import java.util.ArrayList; 10 import java.util.Arrays; 11 import java.util.Collections; 12 import java.util.Scanner; 13 14 public class xinxi{ 15 private static ArrayList<Student> studentlist; 16 public static void main(String[] args) { 17 studentlist = new ArrayList<>(); 18 Scanner scanner = new Scanner(System.in); 19 File file = new File("F:\\身份证号.txt"); 20 try { 21 FileInputStream fis = new FileInputStream(file); 22 BufferedReader in = new BufferedReader(new InputStreamReader(fis)); 23 String temp = null; 24 while ((temp = in.readLine()) != null) { 25 26 Scanner linescanner = new Scanner(temp); 27 28 linescanner.useDelimiter(" "); 29 String name = linescanner.next(); 30 String number = linescanner.next(); 31 String sex = linescanner.next(); 32 String age = linescanner.next(); 33 String province =linescanner.nextLine(); 34 Student student = new Student(); 35 student.setName(name); 36 student.setnumber(number); 37 student.setsex(sex); 38 int a = Integer.parseInt(age); 39 student.setage(a); 40 student.setprovince(province); 41 studentlist.add(student); 42 43 } 44 } catch (FileNotFoundException e) { 45 System.out.println("学生信息文件找不到"); 46 e.printStackTrace(); 47 } catch (IOException e) { 48 System.out.println("学生信息文件读取错误"); 49 e.printStackTrace(); 50 } 51 boolean isTrue = true; 52 while (isTrue) { 53 System.out.println("输入序号进行相应的操作"); 54 System.out.println("1.字典排序"); 55 System.out.println("2.输出年龄最大和年龄最小的人"); 56 System.out.println("3.查找与你年龄相近的人"); 57 System.out.println("4.查找你的同乡"); 58 String n = scanner.next(); 59 switch (n) { 60 case "1": 61 Collections.sort(studentlist); 62 System.out.println(studentlist.toString()); 63 break; 64 case "2": 65 int max=0,min=100; 66 int j,k1 = 0,k2=0; 67 for(int i=1;i<studentlist.size();i++) 68 { 69 j=studentlist.get(i).getage(); 70 if(j>max) 71 { 72 max=j; 73 k1=i; 74 } 75 if(j<min) 76 { 77 min=j; 78 k2=i; 79 } 80 81 } 82 System.out.println("年龄最大:"+studentlist.get(k1)); 83 System.out.println("年龄最小:"+studentlist.get(k2)); 84 break; 85 case "3": 86 System.out.println("年龄:"); 87 int yourage = scanner.nextInt(); 88 int near=agenear(yourage); 89 int value=yourage-studentlist.get(near).getage(); 90 System.out.println("和你年龄相近的是"+studentlist.get(near)); 91 break; 92 93 case "4": 94 System.out.println("输入你的家乡"); 95 String find = scanner.next(); 96 String place=find.substring(0,3); 97 for (int i = 0; i <studentlist.size(); i++) 98 { 99 if(studentlist.get(i).getprovince().substring(1,4).equals(place)) 100 System.out.println("你的同乡是 "+studentlist.get(i)); 101 } 102 break; 103 104 } 105 } 106 } 107 public static int agenear(int age) { 108 int j=0,min=53,value=0,k=0; 109 for (int i = 0; i < studentlist.size(); i++) 110 { 111 value=studentlist.get(i).getage()-age; 112 if(value<0) value=-value; 113 if (value<min) 114 { 115 min=value; 116 k=i; 117 } 118 } 119 return k; 120 121 122 } 123 124 125 }
1 package xinxi; 2 3 4 5 public class Student implements Comparable<Student> { 6 7 private String name; 8 private String number ; 9 private String sex ; 10 private int age; 11 private String province; 12 13 public String getName() { 14 return name; 15 } 16 public void setName(String name) { 17 this.name = name; 18 } 19 public String getnumber() { 20 return number; 21 } 22 public void setnumber(String number) { 23 this.number = number; 24 } 25 public String getsex() { 26 return sex ; 27 } 28 public void setsex(String sex ) { 29 this.sex =sex ; 30 } 31 public int getage() { 32 33 return age; 34 } 35 public void setage(int age) { 36 this.age= age; 37 } 38 39 public String getprovince() { 40 return province; 41 } 42 public void setprovince(String province) { 43 this.province=province ; 44 } 45 46 public int compareTo(Student o) { 47 return this.name.compareTo(o.getName()); 48 } 49 50 public String toString() { 51 return name+"\t"+sex+"\t"+age+"\t"+number+"\t"+province+"\n"; 52 } 53 }
实验结果如下图
实验4:内部类语法验证实验
实验程序1:
l 编辑、调试运行教材246页-247页程序6-7,结合程序运行结果理解程序;
l 了解内部类的基本用法。
实验程序2:
l 编辑、调试运行教材254页程序6-8,结合程序运行结果理解程序;
l 了解匿名内部类的用法。
实验程序3:
l 在elipse IDE中调试运行教材257页-258页程序6-9,结合程序运行结果理解程序;
l 了解静态内部类的用法。
实验总结
掌握了接口的定义用法;掌握了实现接口类的定义要求和使用要,对程序回调设计模式和Comparator接口用法也有相应的了解与程序的理解。
在老师及助教学长的引领下,关于对象浅层拷贝与深层拷贝方法了解的相当透彻,自己也通过书籍和网上的精彩帖子了解到更多。
此外对Lambda表达式语法和内部类的用途及语法要求做了相应的了解。
最后,关于此次的编程任务,是建立在前几次的读取txt文件实验的内容上做了相应的拓展,完成的较为理想,对程序理解的也很透彻,但还是有些不了解的地方,通过网上搜寻和向同学提问也得到了相应的解答,最终解决了问题,得出最终结果。相较前几次实验有所提高,还需继续努力。