プロジェクト |
コンテンツ |
「オブジェクト指向プログラミング(Javaの)」 |
https://home.cnblogs.com/u/nwnu-daizh/ |
どこの仕事でこの要件 |
https://www.cnblogs.com/nwnu-daizh/p/11703678.html |
ジョブの学習目標 |
|
エッセイボーエン本文の内容は次のとおりです。
パートI:第六章では、理論的な知識をまとめた(30ポイント)
まず、インタフェース:
(1)インターフェースはクラスではなく、クラスの説明のための要件のセットは、これらのクラスは、均一な形式で記述インターフェイスに従うことが規定されています。クラスは、特定のインターフェイスに従った場合は、このサービスを実行します。
(2)Javaは多重継承をサポートしていない、それはサブクラスは一つだけの親を持つことができますであり、単一継承は、管理しやすい、Javaが簡単になりますが、あなたは、単一継承の欠点を克服したい場合はインタフェース技術を使用しますが、クラスが実装することができています複数のインタフェースは、インタフェースを定義するキーワードinterfaceキーワードを使用します。
インタフェース(3)状態:インターフェースのインターフェース名と、そのインタフェース:のみ許可メソッドを実装宣言定義、定数定義及び方法を含みます。
(4)使用インタフェース:クラスAの追加、印刷を実装するか、クラスAがA1印刷を実装延び、追加
(5)インターフェース方法は、自動的に必要ではないインターフェイス宣言方法は、キーワードパブリックを提供する場合、従って公衆に属し、。
1)指定されたインターフェースを実装するクラスを宣言する:(6)インタフェースは、クラスがインターフェイスを実装できるようにするために、そのクラスにインターフェースを実装することにより行われるべきタスクインスタンスフィールドおよび実装の方法を提供すること、インスタンス・フィールドを含めることはできません。2)すべてのインタフェースのメソッドが定義します。
(8)クラスのインタフェースを使用する場合、達成する全ての方法、プロセスのタイプを指定する必要があり、およびパラメータは一貫インターフェースでなければならず、インターフェースメソッドのパブリック抽象デフォルト、それがリーク書かれた公共の達成に基づいてはなりませんキーワード;インターフェイス一定のデフォルトのキーワードのpublic static。
(9)INTのcompareTo(T他)
オブジェクトが他の負の値が戻されるよりも小さい場合、それらが等しい場合、この比較のために他のオブジェクトと、次いで、そうでなければ正の値を0に戻します。
静的な無効ソート(オブジェクト[] a)の
配列の要素の並べ替えを使用してマージソートアルゴリズム。配列で必要な要素は、要素間のComparableインタフェースを実装するクラスに属していなければならないと同等でなければなりません。
静的INTコンペア(int型のx、int型のY)7
X <場合yはxとyが等しい場合、負の整数を返す0を返し、そうでなければ負の整数。
静的INT比較(ダブルのx、ダブルy)は1.4
X <場合yはxとyが等しい場合、負の数を返す0を返し、そうでなければ負の数。
(10)インターフェースが新たなオペレータインタフェースをインスタンス化するために使用することができない、クラスではなく、X =新しい同等(...); // ERROR
私たちは、オブジェクト・インターフェースを構築することはできませんが、変数のインタフェースを宣言することができ、インタフェース変数は、オブジェクトのインタフェースは、オブジェクトのインスタンスは、特定のインタフェースを実装しているかどうかをチェックするために使用することができます実装するクラスを参照する必要があります。
インターフェースとして(11)は、抽象公共および定数のみのpublic static finalメソッドが含まれているので、インターフェイスを記述する時間がキーワードを省略してもよいです。
(12)戻り型がvoidインターフェイスでない場合場合、その実装は、少なくとも1つの戻りステートメントを有し、戻り型がvoidインタフェースである場合、括弧に加えて声明することはできません。
(13)インターフェースは、それぞれのJavaパッケージで提供され、インタフェースは、対応するパケットを導入することによって使用することができる、カスタムインタフェースであってもよい、ソース文書は、そのクラスとインタフェースです。
メソッド・インターフェース(14)とクラスは、インターフェイスは、一定のオブジェクトクラスを介して呼び出すことができる実装し、定数は、クラス名とインタフェース名で呼ばれてもよいです。
何公衆が存在しない場合(15)場合公衆キーワードと結合されている場合インターフェイス宣言は、その後インターフェイスが呼び出されるクラスのいずれかであることができる、使いやすいインターフェイスは、クラスが同じパッケージ内に呼び出すことができました。
親クラスがインターフェイスを使用している場合(16)、次いで、サブクラスは、器具を使用する必要がインターフェイスを使用しないであろう。
(17)インターフェイスを拡張するインタフェースによって継承することができます。
(18)は、クラス宣言がインタフェースを実装していますが、インターフェイスのすべてのメソッドを実装していない場合は、そのクラスは抽象クラスであるようになりました。
(19)静的メソッド:界面における増加静的メソッドを可能にするJava SE 8から開始し、静的メソッドのみができる静的メソッド実装するメソッド本体を提供する接口名.静态方法
呼び出すことを。限り、方法の前の静的キーワードを適用することができるように達成するための構文は、それは理論的に可能であるが、これは抽象仕様としてインターフェースの本来の意図に反しています。静的メソッドは、実装クラスを継承することができ、それが実装クラスでオーバーライドすることはできません。
(20)デフォルトの方法は:インターフェースのメソッドは、デフォルトのメソッド本体の実装として提供することができる、デフォルトの修飾子は、デフォルトのインターフェイスを取得することができ、このメソッドをオーバーライドすることができ、このサブクラスことなく、従来の方法に加えることができます。この方法は、デフォルトの実装クラスを書き換えることが可能。インタフェースの実装クラス名.superで使用されるデフォルトのメソッドを呼び出します。デフォルトのメソッドが呼び出されます。
競合を解決する(21)デフォルトの方法。
あなたが最初のインターフェイスにメソッドを定義する場合、デフォルトのメソッド、スーパークラスまたは他のインターフェイス、紛争の同じ方法の後、定義されます。次のように競合のルールは以下のとおりです。
- スーパークラスおよびインタフェースコンフリクト。スーパークラスは、具体的な方法を提供した場合は、優先順位のスーパークラスの原則によると、それは無視される引数の同じタイプのデフォルトメソッドと同じ名前を持ちます。
- 複数のインターフェイス間の競合。実装クラスが複数のインタフェースを実装する場合、一つのインタフェースは、デフォルトの方法を提供し、さらにインターフェースを同様に同じ名前とパラメータタイプ(デフォルトパラメータかどうか)が設けられており、衝突が発生した場合のインタフェースを実装しなければなりませんクラスは、競合を解決するには、このメソッドをオーバーライドします。
(22)同じ名前定数の溶液。
1.スーパークラスおよびインタフェースコンフリクト。クラスはスーパークラスを継承し、インターフェイスの数を実装している場合、この時点で競合スーパーの優先原則のデフォルトの方法と同じではありません。競合を覆うことのみ実装クラスの定数によって解決することができます。
複数のインターフェース間2.競合。クラスは複数のインタフェースを実装する場合、これらのインターフェースは、一定、次いでコンフリクトと同じ名前を持ちます。あなたは、である必要があります接口名.常量
正確に使用する定数を示す方法。
(23)コンパレータインタフェース:コンパレータは、インターフェイス「コンパレータ」のインターフェイスは、サイズ比較照合などをカスタマイズするために使用できる汎用インタフェースであることを意味します。ソーティングカスタマイズするために、メソッドは、パラメータとして配列、およびコンパレータを提供することは、Arrays.sort望ましいバージョンをオーバーロードされています。
(24)オブジェクトクローン:元の変数のコピーと変更が別の変数に一つの変数に影響を与えることを示す、同じオブジェクトを指します。オブジェクトのオリジナルがあれば、我々はそれが初期状態と同じですが、彼らは自分のさまざまな状態に戻った後、この場合、クローンに使用することができるように、オリジナルをコピーしたオブジェクトを作成したいです。clone()メソッドは、メソッドCloneableインタフェースが、保護されたメソッドオブジェクトではありません。Cloneableインタフェースは、場合にのみ、クラスがCloneableインタフェースを実装し、クローン()メソッドはCloneNotSupportedExceptionをスローします呼び出すしないことを提供します。
(25)抽象クラスとインタフェース。
違い:
すべての変数について1.インタフェースは、最終的な静的パブリックでなければなりません。無制限の抽象クラス変数
インタフェースのメソッドが構成されていない2.、新しい演算子をインスタンス化することはできません。抽象クラスは、コンストラクタメソッドを持つ、サブクラスチェーンでコンストラクタを呼び出すことで、new演算子をインスタンス化していません
3.すべてのインターフェースは、パブリック抽象インスタンスメソッド(ジャワSE 8つの静的メソッド定義された開始許可)、無制限の抽象クラスである必要があります
4.クラスが一つだけの親クラスを継承することができますが、複数のインタフェースを実装することができます
5.クラスのすべてが共通のルートクラスObjectインタフェースは共通のルートではありません持っています
インターフェイスとサブクラスとの間の関係が弱い関係「が」一方抽象クラスと強くなければならないサブクラスの間の6の関係は、関係(強い関係)「である」(弱い関係) 。インターフェースはあなたがすべてのクラスの同じタイプに属する必要はありませんが、行動の統一コードを持っている必要がありますので、インタフェースを実装する抽象クラス、サブクラスよりも柔軟です。
二、ラムダ式:
(1)ラムダ式は、それが一回または複数回の後にすることができ、コードのブロックを送信することが可能です
(2)ラムダ式の構文:
それは3つの部分から構成さ
-
パラメータの形式でカンマ区切りブラケット、パラメータは、メソッドインターフェイス関数式のパラメータであります
-
矢印記号: - >
-
コードブロックを{}でラップ、および戻り値を返す必要がなければならない場合の構築物、及びコードブロックは、式、メソッド内部身体機能インターフェース実装することができるが、例外は、ある関数式場合インターフェースメソッドの戻り値の側面は{}せず、無効です
(3)機能インタフェース:そのようなインタフェースの必要性は、ラムダ式を提供することができる抽象メソッドへの唯一のインターフェースは、インターフェース機能は、インタフェースと呼ばれます。
(4)メソッドの参照は:ラムダ式は、参照される方法は、身体のラムダ式を達成するための方法は、容器は、中央(クラス名、インスタンス名であってもよい)残され、構文は非常に簡単で、実際に簡略化表現であり、実際にされています「::」の右には、対応するメソッド名です。
リファレンスの形式は、一般的な方法であり、
-
メソッドが静的である場合、それはクラス名:: methodNameのです。このようなオブジェクト::対等に
-
それはインスタンスメソッドである場合、それはインスタンス:: methodNameのです。オブジェクトOBJ =新しいオブジェクト(); objが::等しいです。
-
コンストラクタは。クラス名です::新
(5)基準コンストラクタ:コンストラクタ参照は同様の方法を引用したが、この方法は、新しい名前が付けられます。例えば、Employee::new
従業員コンストラクタへの参照。ような、コンテキストに応じてコンストラクタとしてFunction<Integer,Employee> func1 = Employee :: new;
の等価Function<Integer,Employee> func = x -> new Employee(x);
配列型はまた、参照としてコンストラクタ、あるint[]::new
ラムダ式に相当x -> new int[x]
(6)ラムダ式を扱います:
私たちは、ラムダ式の焦点は実行を遅らせることがある、前に将来の希望の理由を述べた後、コードを実行する、など、多くの理由が、あります。
1.別のスレッドでコードを実行します。
2.コードを複数回実行します
適切な位置に前記アルゴリズムの実行コード(例えば、比較演算は、ソートに)
前記実行コードがある場合に発生する(例えば、ボタンのクリックなどのデータが到着します)
5.コードを実行し、必要な場合にのみ
以下は、インタフェースの基本的なタイプの共通インタフェース機能と機能です。
(7)なぜ私たちはラムダ式が必要です。
三つの主要な理由があります。
1.よりコンパクトなコード
2.の方法を変更する機能を
マルチコア処理3.ベターサポート
第三に、内部クラス:
(1)内部クラス、またはネストされたクラスとして、別のクラスは、クラス定義された範囲です。クラスのような従来型として使用することができます。クラスのみ、その外部のクラスで使用される場合、典型的には、それは内部クラスとして定義され、クラス内部機構は、主に相互協力関係を有するクラスのセットを設計するために使用されます。
(2)内部クラスを使用する利点:
1.内部クラスが隠されて実現することができます:一般的な非内部クラスを、プライベートで保護された権利を持つことが許されますが、内部クラスされていません。
2.内部クラスのメンバーは、囲むクラスのアクセスのすべての要素を有する:内部クラスは、すべてのデータ・フィールドにアクセスすることができ、その外側(プライベートデータフィールドを含む)クラスおよびメソッドが含まれ、内部クラスに渡される外部クラスのオブジェクトを参照する必要はありません施工方法は、内部クラスは、外部クラスOuterClass.thisを参照し、明示的に書かれている場合、外部オブジェクトの暗黙的な参照へのポインタを有しています。
3.多重継承は、間接的であることができる:例えば、二つの内部クラスとinnerClass1 innerClass2の定義は、間接的な多重継承を達成するために、その後、クラスAがクラスAのクラスBおよびCのプロパティとメソッドを有するであろう、クラスBおよびクラスCを継承します。
4.コンパイラによって生成されたファイルのバイトコードのクラスファイルのサイズを縮小します。
(3)下のクラスの内部機能を備えています。
- 内部クラスは、名前の中にコンパイルされ
OuterClassName$InnerClassName
たクラス。例えば、クラスは、クラスのメンバーを内部にコンパイルされたテストで定義されています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表达式。