添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
绅士的毛巾  ·  C# ...·  1 年前    · 
爱搭讪的猴子  ·  datagrip postgresql ...·  1 年前    · 

天气晴朗,阳光明媚,学习算法,做作业。

昨天晚上用java 语言做算法作业关于 人-位置 匹配 : 医院和医学院学生配对。 结果被 Dictionary、Enumeration 、Hashtable、HashMap 、Map之间的 关系搞得晕头转向。我不过是想用个字典的数据结构去保存 医院对学生的邀请记录,然后遍历出来罢了, 结果网上五花八方的 代码。 最头痛的是,编译的时候 还老报 找不到符号 的错误。

为了后面的算法作业能够顺利地用java 写完,索性今天就来搞清楚它们之间的关系!
在这里插入图片描述
截图来自:https://www.runoob.com/java/java-map-interface.html

接口:关键字 interface,只定义方法名
对上:接口可以 extends 多个 接口类
对下:可以被接口继承extends,被抽象类、实类 实现 implements

这里先定义一个接口方法 method1,一会用来被抽象类实现

// Api.java
// 对上:接口可以 extends 多个 接口类
// 对下:可以被接口继承extends,被抽象类、实类 实现 implements 
public interface Api {
  public String method1();

抽象类:关键字 abstract,也可以只写方法名,想写点具体的方法代码也行,只是不给直接用
对上:抽象类只能extends一个抽象类、实体类,可以 implements 多个接口
对下:抽象类只能被抽象类、实体类继承 extends 不能被实例化 new , 方法只能被继承了它的类使用

这里定义一个抽象类,写个构造函数,实现接口方法,再重载一下接口方法(方法名不变,增加一个方法参数),然后用来被实体类继承。

//Abs.java
// 对上:抽象类只能extends一个抽象类、实体类,可以 implements 多个接口
// 对下:抽象类只能被抽象类、实体类继承 extends 不能被实例化 new , 方法只能被继承了它的类使用
public abstract class Abs implements Api {
  // 抽象类构造函数
  public Abs() {
    System.out.println("\n constructor Abs:来自abstract abs constructor Abs");
  // implements
  public String method1() {
    System.out.println("abstract method1:来自abstract abs method1");
    return "methods->abs->api";
  // Overload
  public String method1(String str1) {
    System.out.println("abstract method1:来自abstract abs method1 : 重写,一个参数");
    return "methods->abs->api";

实体类:关键字 class ,就是用来继承别的类,实现接口,写自己的方法的类。这下里面的方法都可以用,还可以霍霍被继承来的方法(重写->多态)。
对上:实体类只能extends一个抽象类、实体类,可以 implements 多个接口
对下:实体类只能被抽象类、实体类继承 extends 可以实例化 new

这里定义一个实体类,用来继承抽象类,并实现接口api ,写个构造函数,重写method1, 重载method1为两个参数.

(备注:这里虽然,也写了要实现接口Api,但因为继承的抽象类里面有实现过api的方法,所以实际该实体类可以什么方法都不写,不会报错。具体判断有没有实现接口方法,似乎是在整个继承链路上去找该接口方法是否存在)

// RealParent.java
// 对上:实体类只能extends一个抽象类、实体类,可以 implements 多个接口
// 对下:实体类只能被抽象类、实体类继承 extends 可以实例化 new
public class RealParent extends Abs implements Api {
  RealParent() {
    System.out.println("constructor RealParent:class RealParent extends Abs   constructor RealParent");
  @Override // 重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即
  // 壳不变,核心重写! 
  public String method1() {
    System.out.println("RealParent method1:class RealParent extends Abs  method1 方法,调用父类");
    return super.method1(); // 继承了抽象类,可以通过super 调用抽象父类的方法
  // overload //重载(overloading) 
  // 在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同
  public String method1(String self1, String self2) {
    System.out
        .println("RealParent method1:class RealParent extends Abs  method1 方法, overWrite. 两个参数"+self1+self2);
    return "methods->Real->Abs->api";

子类:继承了别的实体类 的类

写个构造函数,重写被继承来的method1,重写两个参数的method1方法,重载method1 为三个参数

//Real.java
public class Real extends RealParent {
  Real() {
    System.out.println("constructor Real:class Real extends RealParent   constructor Real");
  @Override // 重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即
            // 壳不变,核心重写! 
  public String method1() {
    System.out.println("Real method1:class Real extends RealParent  method1 方法,调用父类");
    return super.method1(); // 继承了父类,可以通过super 调用抽象父类的方法
  @Override
  public String method1(String self1, String self2) {
    System.out.println("Real method1:class Real extends RealParent  method1 方法, overWrite. 两个参数" +self1+self2);
    return "methods->Real->RealParent->Abs->api"; // 继承了父类,可以通过super 调用抽象父类的方法
  // Overload //重载(overloading) 
  // 在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同
  public String method1(String self1, String self2, String self3) {
    System.out
        .println("Real method1:class Real extends RealParent  method1 方法, overWrite. 三个参数" +self1+self2+self3);
    return "methods->Real->RealParent->Abs->api";

这里开始观察,用 上面定义好的 接口、抽象类、实体类、子类 分别声明 一个 变量;
统一new 一个 Real类 赋值给这个变量;
分别调用这个变量的 method1 方法:无参数、一个参数、2个参数、3个参数,
看会发生什么?

结果1: 下面被注释掉的 方法调用,都是因为会报错 not applicable 的错误, 在申明的类中,这个方法不适用!
这个声明的类 可以起到过滤 赋值类的方法的作用!

// App.java
public class App{
  public static void main(String[] args) {
    // Map m1 = new HashMap();
    Real r = new Real();
    System.out.println("main: 实例化Real,调用method1方法   Real类型");
    System.out.println(r.method1());                      //Api.java中首次出现
    System.out.println(r.method1("haha Real,一个参数"));  //Abs.java中首次出现
    System.out.println(r.method1("haha Real","两个参数"));//RealParent.java 中首次出现
    System.out.println(r.method1("haha Real","两个参数","三个参数")); // Real.java 中首次出现
    Api r2 = new Real();
    System.out.println("main: 实例化Real,调用method1方法   Api类型");
    System.out.println(r2.method1());
    // System.out.println(r2.method1("haha Api,一个参数"));
    // System.out.println(r2.method1("haha Api","两个参数"));
    // System.out.println(r2.method1("haha Api","两个参数","三个参数"));
    Abs r3 = new Real();
    System.out.println("main: 实例化Real,调用method1方法   Abs类型");
    System.out.println(r3.method1());
    System.out.println(r3.method1("haha Abs,传入一个参数"));
    // System.out.println(r3.method1("haha ABS"," 传入两个参数"));
    // System.out.println(r3.method1("haha ABS"," 传入两个参数","三个参数"));
    RealParent r4 = new Real();
    System.out.println("main: 实例化Real,调用method1方法   RealParent类型");
    System.out.println(r4.method1());
    System.out.println(r4.method1("haha RealParent,传入一个参数"));
    System.out.println(r4.method1("haha RealParent"," 传入两个参数"));
    // System.out.println(r4.method1("haha RealParent"," 传入两个参数","三个参数"));

编译代码并运行

javac -encoding utf-8  *.java    # 编译
java App >> App.txt              #执行并将结果写入 App.txt 文件中

App.txt

来看看,都输入了什么,观察一下方法的调用顺序:

constructor Abs:来自abstract abs constructor Abs constructor RealParent:class RealParent extends Abs constructor RealParent constructor Real:class Real extends RealParent constructor Real main: 实例化Real,调用method1方法 Real类型 Real method1:class Real extends RealParent method1 方法,调用父类 RealParent method1:class RealParent extends Abs method1 方法,调用父类 abstract method1:来自abstract abs method1 methods->abs->api abstract method1:来自abstract abs method1 : 重载,一个参数 methods->abs->api Real method1:class Real extends RealParent method1 方法, overWrite. 两个参数haha Real两个参数 methods->Real->RealParent->Abs->api Real method1:class Real extends RealParent method1 方法, overWrite. 三个参数haha Real两个参数三个参数 methods->Real->RealParent->Abs->api

上面只放了 实例r 输出的结果:
通过结果可以知道:代码的执行顺序:

抽象类constructor -> 实体类constructor ->子类constructor -> main 中的输出 ->

{ 零个参数的Method1方法 real中重写后的Real method1()->super中调用 RealParent method1() 重写-> super 中调用abstract method1 } ->

带一个参数的Method1方法,Real 中没有,RealParent中没有,Abs 中有,调用abstract method1 ->

带两个参数的Method1方法,Real中有,RealParent有,Real 重写了 RealParent两个参数的方法,所以调用 Real method1 ->

带三个参数的Method1方法,Real中有,其他没有,调用Real method1。

总结:
1、 new 一个实例化对象时,会从继承链的 最底层 构造函数依次向上外执行 。
2、执行方法时会从外向内找符合 方法名、参数名的 方法调用,直到找到后就执行。

起过滤作用的 变量声明类型

初始化 4 种类型(real、Api、Abs、RealParent )的 r ,并用实例化后的Real 对象去赋值

既 在java中存在 以下四种 变量声明的形式:

1、 类 变量 = new 类名()
2、 接口 变量 = new 类名()
3、 抽象类 变量 = new 类名()
4、 父类 变量 = new 类名()

 Real r = new Real();          //  可用的 method1 的数量为:4
 Api r2 = new Real();          //  可用的 method1 的数量为:1
 Abs r3 = new Real();          //  可用的 method1 的数量为:2
 RealParent r4 = new Real();   //  可用的 method1 的数量为:3

当声明的类型typeA 和 赋值实例化的类型type B 不一致时,
两种类型的继承链路上的方法集合 存在以下关系:

若A∈B 则可以使用以下声明以及初始化语句,否则会报不兼容的错误。
typeA 变量c = new typeB();

实体对象 可访问的方法数量 = A∩B = A
实体对象 不可访问的方法数量 = A在B中的相对补集 = ∁UA

哦,终于搞清楚了 java 中的 神出鬼没的 接口 和 抽象类 。

看过java的数据结构后,还是觉得 前端的 对象 最好用,虽然java 中提供多种数据结构,但是方法未免也太多了。

看完 JavaScript 描述版本的 《数据结构与算法》 后觉得 光靠 Array 和 Object 就能实现大部分 的数据结构。

然而… 目前为止学习的过程中已经出现 Pascal、C++、java、python…

在java中存在 以下四种 变量声明的形式: 1、 类 变量 = new 类名() 2、 接口 变量 = new 类名() 3、 抽象类 变量 = new 类名() 4、 父类 变量 = new 类名()声明类型可以起到精简 方法数量的作用。来来里,一起熟悉下方法的调用顺序以及 报错的表现形式 定义 :指描述可属于任何类或结构的一组相关功能。 接口的成员可以是方法(不能有方法体),属性,事件和索引器,但不能包含常数,字段,运算符,实例构造函数析构函数或类,也不能包括任何种类的静态成员,接口中的成员不允许添加访问修饰符,(默认都是public) 1. 接口一个引用类型,通过接口可以实现多重继承。 2. C#中接口的成员不能有new、public、protected、internal、private等修饰符。 3. 接口中只能声明”抽象”成员(所以不能直接下一步对接口进行 rect = RectangleImpl(5, 10) print("长方形的面积为:", rect.area()) print("长方形的周长为:", rect.perimeter()) 这段代码定义了一个抽象类 `Rectangle`,其中声明了两个抽象方法 `area` 和 `perimeter`,分别用于计算长方形的面积和周长。然后定义了一个实现类 `RectangleImpl`,该类继承了 `Rectangle` 抽象类,并实现了其中的两个抽象方法。最后,我们可以创建一个 `RectangleImpl` 的实例,并调用其 `area` 和 `perimeter` 方法来计算长方形的面积和周长。
nodejs 下使用js封装console.log方法输出自定义的彩色字体,遇到Octal escape sequences are not allowed in template strings weixin_41899459: 不顶用啊,放在模版字符串${}里还是报错 nodejs 下使用js封装console.log方法输出自定义的彩色字体,遇到Octal escape sequences are not allowed in template strings TypeScript是什么?TypeScript入门,第四遍学习——拨开TypeScript掀开过又关上的面纱(* ̄rǒ ̄) window10 64系统中node-gyp的环境配置,为了在nodejs环境下访问sqlserver而用node-gyp,从热情到放弃系列