201871010102-常龙龙《面向对象程序设计(java)》第八周学习总结

项目

内容

这个作业属于哪个课程

https://www.cnblogs.com/nwnu-daizh/

这个作业的要求在哪里

https://www.cnblogs.com/nwnu-daizh/p/11703678.html

作业学习目标

  1. 掌握接口定义方法;
  2. 掌握实现接口类的定义要求;
  3. 掌握实现了接口类的使用要求;
  4. 理解程序回调设计模式;
  5. 掌握Comparator接口用法;
  6. 掌握对象浅层拷贝与深层拷贝方法;
  7. 掌握Lambda表达式语法;
  8. 了解内部类的用途及语法要求。

第一部分:总结第六章理论知识(30分)

一、接口

1.接口技术主要用来描述类具有什么功能,而并不给出每个功能的具体实现。一个类可以实现一个或多个接口,并在需要接口的地方,随时使用实现了相应接口的对象

●Java为了克服单继承的缺点,Java使用了接口,一 -个类可以实现-一个或多个接口。
●在Java中,接口不是类,而是对类的-组需求描述,由常量和一组抽象方法组成。
●接口中不包括变量和有具体实现的方法。
●只要类实现了接口,则该类要遵从接口描述的统一 格式进行定义,并且可以在任何需要该接口的地方使用这个类的对象。

●接口类型
    1.用户自定义接口

     2.标准接口。

2.自定义接口的声明 

1>声明方式:public interface 接口名

{.....}

2> 接口体中包含常量定义和抽象方法定义,接口中
只进行方法的声明,不提供方法的实现。

3> 说明

(1) 通常接口的名字以able或ible结尾;
(2) 可以使用ex tends来继承接口的常量和抽象方法,扩展形成新的接口;
(3) 接口中的所有常量必须是public static final,方法必须是public abstract,这是系统默认的,不管你在定义接口时,写不写修饰符都是一样的。

3.接口的实现

● 在类声明时用implements关键字声明使用一个或多个接口
class Employee implements Printable
{ ....... }

●一个类使用了某个接口,那么这个类必须实现该接口的所有方法,即为这些方法提供方法体。

●一个类可以实现多个接口,接口间应该用逗号分隔开。
class Employee implements Cl oneable, Comparable

{.....}

说明:

(1)若实现接口的类不是抽象类,则必须实现所有接口的所有方法,即为所有的抽象方法定义方法体。
(2)一个类在实现某接口抽象方法时,必须使用完全相同的方法名、参数列表和返回值类型。
(3)接口抽象方法的访问控制符已指定为public,所以类在实现时,必须显式地使用public修饰符,否则被警告缩小了接口中定义的方法的访问控制范围。

4.接口的使用

●接口不能构造接口对象,但可以声明接口变量以指向一个实现了该接口的类对象。

Comparable x = new Comparabe() ;//error
Comparable x= new Employee();  //0K 

●可以用instanceof检查对象是否实现了某个接口

     if (an0bject instanceof Comparable)
     { ......}

5.接口与抽象类的区别:

(1)接口不能实现任何方法,而抽象类可以。

(2)类可以实现许多接口,但只有一个父类。

(3)接口不是类分级结构的一部分,无任何联系的类可以实现相同的接口。

 二、Lambda表达式

1.Lambda表达式的语法基本结构(arguments)->body

   有如下几种情况: ●参数类型可推导时,不需要指定类型,如(a)->System.out.println(a)

                                 ●只有一个参数且类型可推导时,不强制写(),如a->System.out.println(a)

                                 ●参数指定类型时,必须有括号,如(inta)>System.out.println(a)

                                 ●参数可以为空,如()->System.out.println(“hello”)

                                 ● body需要用包含语句,当只有一条语句时&可省略;

2.Java Lambda表达式是Java8引入的一个新的功能,主要用途是提供一个函数化的语法来简化编码。

   Lambda表达式本质上是一个匿名方法。

     public int add(int x,int y){returnx+y;}

   转成Lambda表达式后是这个样子:(int x,int y)->x+y;

   参数类型也可以省略,Java编译器会根据上下文推断出来:(x,y)->x+y;//返回两数之和或者(x,y)->{returnx+y;}//显式指明返回值

 三、内部类

1.内部类(inner class)是定义在一个类内部的类。外层的类成为外部类(outer class).内部类主要用于事件处理。使用内部类的原因:

           ●内部类方法可以访问该类定义所在的作用域中的数据, 包括私有的数据。
           ●内部类可以对同一个包中的其他类隐藏起来。
            ●当想要定义一个回调函数且不想编写大量代码时,使用匿名 (anonymous) 内部类比较便捷。

2.局部内部类

 ●可以在一个方法中定义局部类,并且不能用public或private访问说明符进行声明,它的作用域被限定在声明这个局部类的块中。

 ●局部类可以对外部世界完全隐藏起来,即使方法所在类中的其他代码也不能访问。除了定义它的方法外,没有任何方法知道它的存在。

 ●局部类的另一个优势:不仅可以访问包含它们的外部类,还可以访问局部变量,但那些局部变量必须被声明为final

3.匿名内部类

●将局部内部类的使用再深人一步。 假如只创建这个类的一个对象,就不必命名了。这种类被称为匿名内部类(anonymous inner class)。

●由于构造器的名字必须与类名相同, 而匿名类没有类名, 所以, 匿名类不能有构造器。取而代之的是,将构造器参数传递给超类 ( superclass) 构造器。尤其是在内部类实现接口的时候, 不能有任何构造参数。如果构造参数的闭小括号后面跟一个开大括号, 正在定义的就是匿名内部类 。

注意:建立一个与超类大体类似(但不完全相同)的匿名子类通常会很方便。不过, 对于 equals 方法要特别当心。

●SuperType可以是接口,内部类就要实现这个接口;也可以是一个类,内部类就要扩展它。

4.静态内部类

.有时使用内部类只是为了把一个类隐藏在另外一个类的内部,并不需要内部类引用外围类对象。为此,可以将内部类声明为 static, 以便取消产生的引用。 只有内部类可以声明为 static。静态内部类的对象除了没有对生成它的外围类对象的引用特权外, 与其他所冇内部类完全一样。在我们列举的示例中, 必须使用静态内部类,这是由于内部类对象是在静态方法中构造的

注意:(1)在内部类不需要访问外围类对象的时候, 应该使用静态内部类。 有些程序员用嵌套类 (nested class ) 表示静态内部类

         ( 2)与常规内部类不同,静态内部类可以有静态域和方法。

      (3)声明在接口中的内部类自动成为 static 和 public 类

第二部分:实验部分

实验1 导入第6章示例程序,测试程序并进行代码注释。

测试程序1:

l 编辑、编译、调试运行阅读教材214页-215页程序6-1、6-2,理解程序并分析程序运行结果;

l 在程序中相关代码处添加新知识的注释。

l 掌握接口的实现用法;

l 掌握内置接口Compareable的用法。

代码如下:

1>Employee类

public class Employee implements Comparable<Employee>
{
   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
    */
   
   //重写接口的compare To方法
   public int compareTo(Employee other)
   {
      return Double.compare(salary, other.salary);
   }
}

2>EmployeeSortTest类

import java.util.*;

/**
 * This program demonstrates the use of the Comparable interface.
 * @version 1.30 2004-02-27
 * @author Cay Horstmann
 */
public class EmployeeSortTest
{
   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);

      //使用mergesort算法对数组staff中的元素进行排序。要求数组中的元素必须实现了Comparable接口中的类,并且元素之间是可比较的。
      Arrays.sort(staff);

      //打印有关所有员工对象的信息
      for (Employee e : staff)
         System.out.println("name=" + e.getName() + ",salary=" + e.getSalary());
   }
}

运行结果如下:

测试程序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);

  }

}

代码及注释如下:

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引用了实现了接口A的类对象
       A a=new C( );
       //使用接口变量调用实现了接口A的类对象的方法
       a.show( );
       System.out.println("g="+C.g);
  }
}

运行结果如下:

测试程序3:

l 在elipse IDE中调试运行教材223页6-3,结合程序运行结果理解程序;

l 26行、36行代码参阅224页,详细内容涉及教材12章。

l 在程序中相关代码处添加新知识的注释。

l 掌握回调程序设计模式;

代码如下:


/**
@version 1.02 2017-12-14
@author Cay Horstmann
*/


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import javax.swing.Timer;


public class TimerTest
{
public static void main(String[] args)
{
TimePrinter listener = new TimePrinter();


// 构造一个调用listener的计时器
// 每1秒一次
Timer timer = new Timer(1000, listener);
timer.start();


// 保持程序运行直到用户选择“确定”
JOptionPane.showMessageDialog(null, "Quit program?");
System.exit(0);
}
}


class TimePrinter implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
System.out.println("At the tone, the time is "
+ new Date());
Toolkit.getDefaultToolkit().beep();
}
}

 

运行结果如下:

测试程序4:

l 调试运行教材229页-231页程序6-4、6-5,结合程序运行结果理解程序;

l 在程序中相关代码处添加新知识的注释。

l 掌握对象克隆实现技术;

l 掌握浅拷贝和深拷贝的差别。

代码如下:

1>Employee类

import java.util.Date;
import java.util.GregorianCalendar;

public class Employee implements Cloneable
{
   private String name;
   private double salary;
   private Date hireDay;

   public Employee(String name, double salary)
   {
      this.name = name;
      this.salary = salary;
      hireDay = new Date();
   }

   public Employee clone() throws CloneNotSupportedException
   {
       //检查调用clone的对象的类有没有实现cloneable接口
       
       
      //调用object.clone()
      Employee cloned = (Employee)super.clone();

      // 克隆可变字段
      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 + "]";
   }
}

2>CloneTest类

/**
 * This program demonstrates cloning.
 * @version 1.11 2018-03-16
 * @author Cay Horstmann
 */
public class CloneTest
{
   public static void main(String[] args) throws CloneNotSupportedException
   {
      Employee 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);
   }
}

运行结果如下:

实验2 导入第6章示例程序6-6,学习Lambda表达式用法。

l 调试运行教材233页-234页程序6-6,结合程序运行结果理解程序;

l 在程序中相关代码处添加新知识的注释。

l 将27-29行代码与教材223页程序对比,将27-29行代码与此程序对比,体会Lambda表达式的优点。

代码如

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" };  //定义数组plants;
      System.out.println(Arrays.toString(planets));
      System.out.println("Sorted in dictionary order:");
      Arrays.sort(planets);//Arrays.sort方法接受Lambda类的对象;
      System.out.println(Arrays.toString(planets));
      System.out.println("Sorted by length:");
      Arrays.sort(planets, (first, second) -> first.length() - second.length());//检查一个字符串是否比另一个短;
      System.out.println(Arrays.toString(planets));//提供lanbda表达式在底层,Arrays.sort方法会接收实现Comparator<string>某各类的对象;
             
      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?");   //保持程序运行,直到用户选择“OK"
      System.exit(0);        
   }
}

运行结果如下:

 

 

注:以下实验课后完成

实验3: 编程练习

编制一个程序,将身份证号.txt 中的信息读入到内存中;

l 按姓名字典序输出人员信息;

l 查询最大年龄的人员信息;

l 查询最小年龄人员信息;

输入你的年龄,查询身份证号.txt中年龄与你最近人的姓名、身份证号、年龄、性别和出生地;

l 查询人员中是否有你的同乡。

代码如下:

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:/java/身份证号.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;
    }
}

运行结果如下:

 

 实验总结:  本周测试中的lamdba表达式我有些没有理解清楚,在听了助教的讲解后,使我自己加深了它的理解。本次实验有很多的测试程序,在写代码注释的时候我更加着重的理解了它们的代码层次。尤其是本章的程序编写题目,虽然刚开始不会做,在读入文件时对于他的位置有些不懂,但在和同学交流之后我正确理解了它的意义。在今后的编程练习题中,我会更加努力,坚持自己写代码,早日提高自己的编程水平。

posted @ 2019-10-21 21:21  北柯  阅读(193)  评论(1编辑  收藏  举报