实验八接口的定义与使用
实验时间 2018-10
理论部分
6.1 接口:用interface声明,是抽象方法和常量值定义的集 合。从本质上讲,接口是一种特殊的抽象类。
在Java程序设计语言中,接口不是类,而是对类 的一组需求描述,由常量和一组抽象方法组成。 接口中不包括变量和实现的方法。接口体中包含常量定义和方法定义,接口中只进 行方法的声明,不提供方法的实现。通常接口的名字以able或ible结尾;接口中的所有常量必须是public static final,方法必须是public abstract,这是 系统默认的,不管你在定义接时,写不写 修饰符都是一样的.接口的实现:一个类使用了某个接口,那么这个类必须实现该 接口的所有方法,即为这些方法提供方法体。一个类可以实现多个接口,接口间应该用逗号分 隔开。接口的使用:接口不能构造接口对象,但可以声明接口变量以指向一个实现了该接口的类对象。可以用instanceof检查对象是否实现了某个接口。
抽象类:用abstract来声明,没有具体实例对象的类,不 能用new来创建对象。
6.2 接口示例
(回调(callback):一种程序设计模式,在这种模 式中,可指出某个特定事件发生时程序应该采取 的动作。Comparator接口所在包: java.util.*Object类的Clone方法:当拷贝一个对象变量时,原始变量与拷贝变量 引用同一个对象。这样,改变一个
变量所引用 的对象会对另一个变量产生影响。如果要创建一个对象新的copy,它的最初状态与 original一样,但以后可以各自改变状态,就需 要使用Object类的clone方法。Object.clone()方法返回一个Object对象。必须进行强 制类型转换才能得到需要的类型。
6.3浅层拷贝与深层拷贝
(1)Java中对象克隆的实现:在子类中实现Cloneable接口。
(2)在子类的clone方法中,调用super.clone()。
6.3 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 需要用 {} 包含语句,当只有一条语句时 {} 可省略
6.4 内部类:是定义在一个类内部的类。
使用内部类的原因有以下三个: –内部类方法可以访问该类定义所在的作用域中 的数据,包括私有数据。内部类能够隐藏起来,不为同一包中的其他类 所见。
–想要定义一个回调函数且不想编写大量代码时, 使用匿名内部类比较便捷。
内部类可以直接访问外部类的成员,包括 private成员,但是内部类的成员却不能被外部 类直接访问。内部类并非只能在类内定义,也可以在程序块内 定义局部内部类。如果构造参数的闭圆括号跟一个开花括号,表明正 在定义的就是匿名内部类。
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]; 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); 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> 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;//name访问器 17 } 18 19 public double getSalary() 20 { 21 return salary; //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) 37 { 38 return Double.compare(salary, other.salary); 39 } 40 }
测试程序2:
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); } }
结果
l 在elipse IDE中调试运行教材223页6-3,结合程序运行结果理解程序;测试程序3:
l 26行、36行代码参阅224页,详细内容涉及教材12章。
l 在程序中相关代码处添加新知识的注释。
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 ActionListener listener = new TimePrinter(); 20 21 // construct a timer that calls the listener 22 // 间隔s 23 Timer t = new Timer(10000, listener);//定义间隔 24 t.start(); 25 26 JOptionPane.showMessageDialog(null, "Quit program?"); 27 System.exit(0); 28 } 29 } 30 31 class TimePrinter implements ActionListener//内置接口 32 { 33 public void actionPerformed(ActionEvent event) 34 { 35 System.out.println("At the tone, the time is " + new Date()); 36 Toolkit.getDefaultToolkit().beep(); 37 } 38 }
测试程序4:
l 调试运行教材229页-231页程序6-4、6-5,结合程序运行结果理解程序;
l 在程序中相关代码处添加新知识的注释。
l 掌握对象克隆实现技术;
l 掌握浅拷贝和深拷贝的差别。
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 15 Employee original = new Employee("John Q. Public", 50000); 16 //Employee是一个自定义类 17 original.setHireDay(2000, 1, 1); 18 Employee copy = original.clone(); 19 copy.raiseSalary(10);//原有对象不会发生变化 20 copy.setHireDay(2002, 12, 31);//更改器 21 System.out.println("original=" + original);//字符串连接 22 System.out.println("copy=" + copy); 23 } 24 catch (CloneNotSupportedException e) 25 { 26 e.printStackTrace(); 27 } 28 } 29 } 30
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 // 调用object.clone() 22 Employee cloned = (Employee) super.clone(); 23 24 // 克隆可变的字段 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
实验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); 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)); 26 27 Timer t = new Timer(1000, event -> 28 System.out.println("The time is " + new Date())); 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 ID; 2 import java.io.BufferedReader; 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.IOException; 7 import java.io.InputStreamReader; 8 import java.util.ArrayList; 9 import java.util.Arrays; 10 import java.util.Collections; 11 import java.util.Scanner; 12 13 public class Main{ 14 private static ArrayList<People> Peoplelist; 15 public static void main(String[] args) { 16 Peoplelist = new ArrayList<>(); 17 Scanner scanner = new Scanner(System.in); 18 File file = new File("D:\\java\\1\\身份证号.txt"); 19 try { 20 FileInputStream fis = new FileInputStream(file); 21 BufferedReader in = new BufferedReader(new InputStreamReader(fis)); 22 String temp = null; 23 while ((temp = in.readLine()) != null) { 24 25 Scanner linescanner = new Scanner(temp); 26 27 linescanner.useDelimiter(" "); 28 String name = linescanner.next(); 29 String ID = linescanner.next(); 30 String sex = linescanner.next(); 31 String age = linescanner.next(); 32 String place =linescanner.nextLine(); 33 People People = new people(); 34 People.setname(name); 35 People.setID(ID); 36 People.setsex(sex); 37 int a = Integer.parseInt(age); 38 People.setage(a); 39 People.setbirthplace(place); 40 Peoplelist.add(People); 41 42 } 43 } catch (FileNotFoundException e) { 44 System.out.println("查找不到信息"); 45 e.printStackTrace(); 46 } catch (IOException e) { 47 System.out.println("信息读取有误"); 48 e.printStackTrace(); 49 } 50 boolean isTrue = true; 51 while (isTrue) { 52 System.out.println("————————————————————————————————————————"); 53 System.out.println("1:按姓名字典序输出人员信息"); 54 System.out.println("2:查询最大年龄人员信息和最小年龄人员信息"); 55 System.out.println("3:输入你的年龄,查询年龄与你最近人的所有信息"); 56 System.out.println("4:查询人员中是否有你的同乡"); 57 58 59 int nextInt = scanner.nextInt(); 60 switch (nextInt) { 61 case 1: 62 Collections.sort( Peoplelist); 63 System.out.println( Peoplelist.toString()); 64 break; 65 case 2: 66 67 int max=0,min=100;int j,k1 = 0,k2=0; 68 for(int i=1;i< Peoplelist.size();i++) 69 { 70 j= Peoplelist.get(i).getage(); 71 if(j>max) 72 { 73 max=j; 74 k1=i; 75 } 76 if(j<min) 77 { 78 min=j; 79 k2=i; 80 } 81 82 } 83 System.out.println("年龄最大:"+ Peoplelist.get(k1)); 84 System.out.println("年龄最小:"+ Peoplelist.get(k2)); 85 break; 86 case 3: 87 System.out.println("place?"); 88 String find = scanner.next(); 89 String place=find.substring(0,3); 90 String place2=find.substring(0,3); 91 for (int i = 0; i < Peoplelist.size(); i++) 92 { 93 if( Peoplelist.get(i).getbirthplace().substring(1,4).equals(place)) 94 System.out.println(Peoplelist.get(i)); 95 96 } 97 98 break; 99 case 4: 100 System.out.println("年龄:"); 101 int yourage = scanner.nextInt(); 102 int near=agenear(yourage); 103 int d_value=yourage-Peoplelist.get(near).getage(); 104 System.out.println(""+Peoplelist.get(near)); 105 /* for (int i = 0; i < Peoplelist.size(); i++) 106 { 107 int p=Personlist.get(i).getage()-yourage; 108 if(p<0) p=-p; 109 if(p==d_value) System.out.println(Peoplelist.get(i)); 110 } */ 111 break; 112 case 5: 113 isTrue = false; 114 System.out.println("退出程序!"); 115 break; 116 default: 117 System.out.println("输入有误"); 118 } 119 } 120 } 121 public static int agenear(int age) { 122 123 int min=25,d_value=0,k=0; 124 for (int i = 0; i < Peoplelist.size(); i++) 125 { 126 d_value= Peoplelist.get(i).getage()-age; 127 if(d_value<0) d_value=-d_value; 128 if (d_value<min) 129 { 130 min=d_value; 131 k=i; 132 } 133 134 } return k; 135 136 } 137 138 139 } 140
1 package ID; 2 public abstract class People implements Comparable<People> { 3 private String name; 4 private String ID; 5 private int age; 6 private String sex; 7 private String birthplace; 8 9 public String getname() { 10 return name; 11 } 12 public void setname(String name) { 13 this.name = name; 14 } 15 public String getID() { 16 return ID; 17 } 18 public void setID(String ID) { 19 this.ID= ID; 20 } 21 public int getage() { 22 23 return age; 24 } 25 public void setage(int age) { 26 // int a = Integer.parseInt(age); 27 this.age= age; 28 } 29 public String getsex() { 30 return sex; 31 } 32 public void setsex(String sex) { 33 this.sex= sex; 34 } 35 public String getbirthplace() { 36 return birthplace; 37 } 38 public void setbirthplace(String birthplace) { 39 this.birthplace= birthplace; 40 } 41 42 public int compareTo(People o) { 43 return this.name.compareTo(o.getname()); 44 45 } 46 47 public String toString() { 48 return name+"\t"+sex+"\t"+age+"\t"+ID+"\t"+birthplace+"\n"; 49 } 50 }
实验结果
实验4:内部类语法验证实验
实验程序1:
l 编辑、调试运行教材246页-247页程序6-7,结合程序运行结果理解程序;
l 了解内部类的基本用法。
1 package innerClass; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import java.util.*; 6 import javax.swing.*; 7 import javax.swing.Timer; 8 9 /** 10 * This program demonstrates the use of inner classes. 11 * @version 1.11 2015-05-12 12 * @author Cay Horstmann 13 */ 14 public class InnerClassTest 15 { 16 public static void main(String[] args) 17 { 18 TalkingClock clock = new TalkingClock(1000, true);//实现了TalkingClock的类对象 19 clock.start(); 20 21 // keep program running until user selects "Ok" 22 JOptionPane.showMessageDialog(null, "Quit program?"); 23 System.exit(0);// 24 } 25 } 26 27 /** 28 * A clock that prints the time in regular intervals. 29 */ 30 class TalkingClock 31 { 32 //声明属性 33 private int interval; 34 private boolean beep; 35 36 /** 37 * Constructs a talking clock 38 * @param interval the interval between messages (in milliseconds) 39 * @param beep true if the clock should beep 40 */ 41 public TalkingClock(int interval, boolean beep) 42 { 43 this.interval = interval; 44 this.beep = beep; 45 }//构造方法 46 47 /** 48 * Starts the clock. 49 */ 50 public void start() 51 { 52 ActionListener listener = new TimePrinter(); 53 Timer t = new Timer(interval, listener); 54 t.start(); 55 } 56 57 public class TimePrinter implements ActionListener//实现ActionListener的公共类TimePrinter 58 { 59 public void actionPerformed(ActionEvent event) 60 { 61 System.out.println("At the tone, the time is " + new Date()); 62 if (beep) Toolkit.getDefaultToolkit().beep(); 63 } 64 } 65 }
实验结果
实验程序2:
l 编辑、调试运行教材254页程序6-8,结合程序运行结果理解程序;
l 了解匿名内部类的用法。
1 package anonymousInnerClass; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import java.util.*; 6 import javax.swing.*; 7 import javax.swing.Timer; 8 9 /** 10 * This program demonstrates anonymous inner classes. 11 * @version 1.11 2015-05-12 12 * @author Cay Horstmann 13 */ 14 public class AnonymousInnerClassTest 15 { 16 public static void main(String[] args) 17 { 18 TalkingClock clock = new TalkingClock();//TalkingClock类声明为私有的 19 clock.start(1000, true); 20 21 // keep program running until user selects "Ok" 22 JOptionPane.showMessageDialog(null, "Quit program?"); 23 System.exit(0); 24 } 25 } 26 27 /** 28 * A clock that prints the time in regular intervals. 29 */ 30 class TalkingClock 31 { 32 /** 33 * Starts the clock. 34 * @param interval the interval between messages (in milliseconds) 35 * @param beep true if the clock should beep 36 */ 37 public void start(int interval, boolean beep) 38 { 39 ActionListener listener = new ActionListener() 40 { 41 public void actionPerformed(ActionEvent event) 42 { 43 System.out.println("At the tone, the time is " + new Date()); 44 if (beep) Toolkit.getDefaultToolkit().beep(); 45 //外围类引用. 46 } 47 }; 48 Timer t = new Timer(interval, listener); 49 t.start(); 50 } 51 }
实验结果
实验程序3:
l 在elipse IDE中调试运行教材257页-258页程序6-9,结合程序运行结果理解程序;
l 了解静态内部类的用法。
1 package staticInnerClass; 2 3 /** 4 * This program demonstrates the use of static inner classes. 5 * @version 1.02 2015-05-12 6 * @author Cay Horstmann 7 */ 8 public class StaticInnerClassTest 9 { 10 public static void main(String[] args) 11 { 12 double[] d = new double[20]; 13 for (int i = 0; i < d.length; i++) 14 d[i] = 100 * Math.random();//算法 15 ArrayAlg.Pair p = ArrayAlg.minmax(d); 16 System.out.println("min = " + p.getFirst()); 17 System.out.println("max = " + p.getSecond()); 18 }//访问器 19 } 20 21 class ArrayAlg 22 { 23 /** 24 * A pair of floating-point numbers 25 */ 26 public static class Pair 27 { 28 //声明私有属性 29 private double first; 30 private double second; 31 32 /** 33 * Constructs a pair from two floating-point numbers 34 * @param f the first number 35 * @param s the second number 36 */ 37 public Pair(double f, double s) 38 { 39 first = f; 40 second = s; 41 } 42 43 /** 44 * Returns the first number of the pair 45 * @return the first number 46 */ 47 public double getFirst() 48 { 49 return first; 50 } 51 // 访问器 52 /** 53 * Returns the second number of the pair 54 * @return the second number 55 */ 56 public double getSecond() 57 { 58 return second; 59 } 60 } 61 62 /** 63 * Computes both the minimum and the maximum of an array 64 * @param values an array of floating-point numbers 65 * @return a pair whose first element is the minimum and whose second element 66 * is the maximum 67 */ 68 public static Pair minmax(double[] values) 69 { 70 double min = Double.POSITIVE_INFINITY; 71 double max = Double.NEGATIVE_INFINITY;//变量 72 for (double v : values) 73 { 74 if (min > v) min = v; 75 if (max < v) max = v; 76 } 77 return new Pair(min, max); 78 } 79 }
实验结果
实验总结
本章主要学习了掌握接口定义方法;实现接口类的定义要求;实现了接口类的使用要求;程序回调设计模式;Comparator接口用法;对象浅层拷贝与深层拷贝方法;Lambda表达式语法;内部类的用途及语法要求。通过对新知识的代码注解,理解起来更加清楚。但是我感觉程序设计回调模式我还不能完全理解,后面我会查阅资料,进行更进一步的学习。