zoukankan      html  css  js  c++  java
  • Java的三大特性总结

    在Java中,面向对象编程有三大特性:封装继承多态

    先来说说封装。

    封装,顾名思义,就是通过抽象数据类型(即ADT,一种为了将数据类型和可能在该数据类型上进行操作而定义的)将数据以及基于数据的操作封装在一起,使之成为独立的“实体”。

    首先先来看一个Person类:

     1 public class Person implements Comparable<Person> {
     2     private String firstname;
     3     private String lastname;
     4 
     5     public String getFirstname() {
     6         return firstname;
     7     }
     8 
     9     public void setFirstname(String firstname) {
    10         this.firstname = firstname;
    11     }
    12 
    13     public String getLastname() {
    14         return lastname;
    15     }
    16 
    17     public void setLastname(String lastname) {
    18         this.lastname = lastname;
    19     }
    20 
    21     @Override
    22     public int hashCode() {
    23         int hash = 7;
    24         hash = 83 * hash + Objects.hashCode(this.firstname);
    25         hash = 83 * hash + Objects.hashCode(this.lastname);
    26         return hash;
    27     }
    28 
    29     @Override
    30     public boolean equals(Object obj) {
    31         //检查参数是否是这个对象的引用
    32         if (this == obj) {
    33             return true;
    34         }
    35         //检查参数是否是正确的类型
    36         if (!(obj instanceof chapter5_reflect.Person)) {
    37             return false;
    38         }
    39         //将参数转换成正确的类型
    40         Person person = (Person) obj;
    41         //对实体域进行匹配
    42         return Objects.equals(this.firstname, person.firstname)
    43                 && Objects.equals(this.lastname, person.lastname);
    44     }
    45 
    46     @Override
    47     public int compareTo(Person o) {
    48         if (this == o) {
    49             return 0;
    50         }
    51         if (null == o) {
    52             return 1;
    53         }
    54         //先判断姓氏是否相同
    55         int comparison = this.firstname.compareTo(o.firstname);
    56         if (comparison != 0) {
    57             return comparison;
    58         }
    59         //姓氏相同则比较名
    60         comparison = this.lastname.compareTo(o.lastname);
    61         return comparison;
    62     }
    63 }

    对于封装的思想,我们需要尽可能的隐藏内部细节,只保留一些对外操作

    例如在Person类中,我简单的定义了两个成员变量firstname和lastname,在setter方法里我们可以设置姓和名的一些格式,如首字母大写,其余小写来进行“格式化”,对外开放getter来获取变量的值。

    现来总结一下封装的优点:

    1.能够更好的把控成员变量,甚至是管理类的内部结构;

    2.良好的封装能够减少耦合,使得代码更加健壮;

    3.外部程序通过对外接口即可进行访问,无需关注实现细节。

    再谈继承

    继承描述的是is-a的关系,它是复用代码的一种方式,思想就在于人们可以基于已存在的类构造一个新类。继承已存在的类就是复用(继承)这些类的方法和域。再次基础上,还可以添加新的方法和域,以满足新的需求。

    下面来看两个例子:

     1 public class Person {
     2 
     3     private String name;
     4     private String sex;
     5     private int age;
     6 
     7     Person(String name, String sex, int age) {
     8         this.name = name;
     9         this.sex = sex;
    10         this.age = age;
    11     }
    12 
    13     //省略setter和getter方法...
    14  }
     1 public class Yang extends Person {
     2 
     3     Yang(String name, String sex, int age) {
     4         super(name, sex, age);
     5     }
     6 
     7     public String getName() {
     8         return super.getName() + " is " + "genius";
     9     }
    10 
    11 }
    1   public static void main(String... argc) {
    2 //        Yang yang = new Yang("yang", "male", 23);
    3         Person person = new Yang("yang", "male", 23);
    4         out.print(person.getName());
    5     }

    输出: yang is genius 

    注意,如果父类没有默认的构造器,子类构造函数中需要指定父类的构造器,否则编译将会失败!

    从上面的代码中不得不引出关于继承的三大重要的东西,即构造器protected关键字以及向上转型

    1.我们知道,构造器是不能被继承的,只许被调用!

    需要注意的是,子类是依赖于父类的(这也说明了一个弊端,即继承是一种强耦合关系),子类拥有父类的非private属性和方法(弊端二:破坏了封装),所以父类应先于子类被创建。

    所以当父类没有默认构造器时,子类需要指定一个父类的构造器,并且写于子类构造器的第一行!当然父类有默认构造器,子类就无需super了,Java会自动调用。

    2.再说protected关键字。插一句,只有合理使用访问修饰符,程序才能更好的为我们服务!

    对于子类,为了使用父类的方法,我们可以修改它的访问修饰符为protected,而不是一股脑儿的写上public!一劳永逸的做法可能会带来更大的危害!

    而对于类的成员变量,继续保持它的private!

    3.最后是向上转型了,它是一个重要的方面。从上面的的代码中,我写上了Person person = new Yang("yang", "male", 23); 这样结果是将Yang向上转型为Person,带来的影响可能就是属性和方法的丢失,但是它将是安全的。

    同时它最大的作用是.....子类能够提供父类更加强大的功能以适用于不同的场合,完成不同的操作

    不太清楚可以看看这两个: List<String> arrayList = new ArrayList<>(); 和 List<String> linkedList = new LinkedList<>(); 

    我们知道ArrayList是数组实现,查找更快;而LinkedList是链表实现,添加元素和删除元素效率更好!

    但是向上转型有一个弊端,指向子类的父类引用因为向上转型了,它将只拥有父类的属性和方法,同时子类拥有而父类没有的方法,是无法使用了的!

    所以,继承实现了软件的可重用性可拓展性。但是Java是单继承的,并且继承也有多个弊端(上面有提),其实还有一个弊端是父类一旦改变,子类可能也得进行改变!所以慎用吧。

    最后一个特性是多态了。多态性就是不同的子类型可以对同一个请求做出不同的操作。同时多态性分为编译时多态性运行时多态性,对应着方法重载overload和方法重写override

    对于方法重写,存在在继承中。它作为运行时多态性的表现,首先需要子类继承和实现父类的方法,然后向上转型,父类引用子类对象,对同一件事作出不同的响应。

    方法重写时,需要注意的是子类的访问修饰符的访问范围不能小于父类,如父类的一个方法修饰符为protected,那么子类继承时,只能选用public或者protected。除了访问修饰符,其余完全相同于父类!

    对于方法重载,出现在同一个类中,它是编译时多态性的表现。定义为:同名的方法如果有不同的参数列表便视为重载。

    最后有一道经典的题目作为结尾,我也不知道出自哪....Look and think!

     1 public class A {
     2 
     3     public String show(D obj) {
     4         return ("Father and D");
     5     }
     6 
     7     public String show(A obj) {
     8         return ("Father and Father");
     9     }
    10 }
    11 
    12 class B extends A {
    13 
    14     public String show(B obj) {
    15         return ("Child and Child");
    16     }
    17 
    18     public String show(A obj) {
    19         return ("Child and Father");
    20     }
    21 }
    22 
    23 class C extends B {
    24 }
    25 
    26 class D extends B {
    27 }
    28 
    29 class Test {
    30     public static void main(String[] args) {
    31         A a1 = new A();
    32         A a2 = new B();
    33         B b = new B();
    34         C c = new C();
    35         D d = new D();
    36 
    37         System.out.println("1--" + a1.show(b));
    38         System.out.println("2--" + a1.show(c));
    39         System.out.println("3--" + a1.show(d));
    40         System.out.println("4--" + a2.show(b));
    41         System.out.println("5--" + a2.show(c));
    42         System.out.println("6--" + a2.show(d));
    43         System.out.println("7--" + b.show(b));
    44         System.out.println("8--" + b.show(c));
    45         System.out.println("9--" + b.show(d));
    46     }
    47 }
  • 相关阅读:
    shell得到两个文件的差集
    shell 单引号&双引号的使用
    kubernetes session and 容器root权限
    docker 使用网络以及容器互联
    倒计时练习
    会话控制
    XML
    AJAX实现搜索智能提示
    弹窗显示详情练习
    三级联动
  • 原文地址:https://www.cnblogs.com/yang21/p/7105187.html
Copyright © 2011-2022 走看看