zoukankan      html  css  js  c++  java
  • 面向对象分析和设计笔记——第3章

    [1]封装性

     对象是Java封装性最大的体现

    public ClassName{
      成员变量/数据成员:访问权限 数据类型 变量名 ;
      成员方法:访问权限 返回值类型 方法名(){函数体;}
      构造方法:访问权限 类名(){}
    }

      对象的创建与使用:1)对象变量(或引用reference)的声明:声明时操作系统仅会在栈(Stack)内为其分配一个存储首地址数据的32位内存空间;

               2)对象的创建:通过new关键字和实参来调用构造函数来构建对象并初始化成员变量/数据成员,此时操作系统才会在堆(Heap)内为对象分配存储对象信息的内存空间,同时将引用地址值返回给Stack中的引用变量;

               3)对象的使用:通过点运算符“.”可以实现对对象属性的访问和方法的调用,reference可以是已初始化的对象变量,也可以是生成对象的表达式,如:

    reference.variable;
    reference.methodName([paramlist]);
    float tx = pointOne.x;
    float tx = new Point2D(100.0, 200.0).x;
    pointOne.setX(300.0);
    new Point2D(100.0, 200.0).setX(300.0);

    注:1){}“类体”或可以认为是“类的作用域”;

      2)Java中的方法只能作为类的一部分创建,所有的方法都不能游离于类之外;调用方法是通过方法名和实参类型来匹配的;

      3)当为某个类撰写多个构造方法时,若想在其中某个构造方法内部调用另一个构造方法,使用this ([参数列表]);

      4)Java中的reference不同于C++,不可以对引用变量进行“加加减减”的操作;

     注:Java基本上是“纯”的面向对象语言,唯一“不纯”的地方在于存在8个基本数据类型(byteshortintlong; floatdouble; char; boolean)为了弥补这个问题,Java提供了基本类库,提供了这8个基本数据类型的包装类(Wrapped type);此外如果精度还是不够,还可以考虑使用BigDecimal和BigInteger这两个类;

     注:1)IEEE754

       2)BigDecimal类

       3)BigInteger类

    [2]继承性

      1)类型为Employee的一个对象首次创建时,或者Employee类的静态方法或数据首次调用时,JVM必须查找环境变量classpath所指定的位置,找出并装载Employee.class;

      2)Employee.class装载后,如果它有超类,那么便会继续装载它的超类,如果超类还有超类,便会继续装载第二个超类,以此类推。从超类到Employee的所有静态初始化模块顺序进行,静态初始化动作仅发生一次

      3)当1)中创建一个Employee对象时,从超类到Employee类,每一类会分别顺序执行如下步骤:Object*4→Person*3→Employee*3

        在堆内分配一个足够的存储空间,reference地址一样;

        系统会先用默认值初始化对象的成员变量;

        执行所有出现于数据定义处的初始化动作;

        执行构造函数;

      4)如果应用程序没有结束,在同一个应用程序中再创建类Employee的对象时,则从3)开始循环执行;

     1 public class Person{
     2     private String name;
     3     private String address;
     4     public Person (String initialName, String initialAddress){
     5         name = initialName;
     6         address = initialAddress;
     7     }
     8     public String getName(){
     9         return name;
    10     }
    11     public String getAddress(){
    12         return address;
    13     }
    14     public String toString(){
    15         return "name:" + name + "|address:" + address;
    16     }
    17 }
     1 public class Employee extends Person{
     2     private double salary;
     3     public Employee(String initialName, String initialAddress, double initialSalay){
     4         super(initialName, initialAddress);
     5         salary = initialSalary;
     6     }
     7     public double getSalary(){
     8         return salary;
     9     }
    10     public void setSalary(double newSalary){
    11         salary = newSalary;
    12     }
    13     public String toString(){//override
    14         return super.toString() + "|salary:" + salary;//return "name:" + getName() + "|address:" + getAddress() + "|salary:" + salary;
    15     }
    16 }

    对象转型:

    向上转型(upcasting)时,父类的引用变量虽然指向子类对象,但不能通过该引用调用子类所特有的方法;如果想通过父类对象的引用调用子类特有的方法,则必须对其进行强制类型转换;upcasting是自然的、合法的,基本都是legal的

    1 Employee employee = new Employee("lee", "99Ave", 30);
    2 Person person = employee;double salary = ((Employee)person).getSalary();

    向下转型(downcasting)有着特殊性:如果父类对象引用指向的是一个子类的对象,则可以使用downcasting,把超类引用显式地转型为一个子类的对象;如果超类对象引用指向的是一个自身类对象则不可以使用downcasting,illegal的

    1 Person person = new Person("lee", "99MainAve");
    2 double salsry = ((Employee))person).getSalary();//ClassCastException

    downcasting常与instanceof操作符合用以避免非法的向下转型

    1 Person person = new Employee("lee", "100 MainAve", 100);
    2 if(person instanceof Employee){
    3     salary = ((Employee)person).getSalary();
    4 }

    重写和重载:

    重写只覆写方法体,返回值类型、方法名、形参类型都完全一样,是子类与父类之间的关系;重载是拓展新的方法,只发生在一个类内,不是多个类之间的关系

    equals();toString();是Java中重写频率最高的两个方法

    1 public Boolean equals(Object o){//因为重写要求形参类型不能变,所以隐式地将子类对象当作父类变量,upcasting
    2     if (o instanceof Employee){
    3         Employee e = (Employee)p;//downcasting
    4         return this.getName().equals(e.getName()) && this.getAddress().equals(e.getAddress()) && this.getSalary() == e.getSalary();
    5     }else{//this 指向调用该方法的实例对象,即equals左边的对象
    6         return false;
    7     }
    8 }//逻辑运算符参与构成的逻辑表达式的运算结果任然是布尔型量

    在大部分类中,继承自Object类的equals()方法都不适用,因此每个类都需要覆写该方法,API中“wrapper classes”、Date、String中可供调用的equals();方法都是经overwrite过的,先在形参除向上转型再在函数体内向下转型是重写equals();方法中的模板

    1 public String toString(){
    2     return "name:" + name'
    3 }

    在大部分类中,继承自Object类的toString()方法也都不适用,因此每个类都需要覆写该方法,如果不覆写则返回@+字符串地址的Hash码;覆写后的toString();方法一般返回一个表示该对象特征的字符串

    final关键字:

    1)final类

      final的类,不能被继承;

     2)final方法

      父类中final的方法,子类中不能overwrite这个方法,但可以overload这个方法;

    3)final变量

      基本类型:不能被再次赋值;对象类型:不能修改指针,但可以修改指针指向的内部的值; 

    [3]多态性:是由继承性带来的

    多态的变量FacultyMember m;//静态绑定,允许将多种类型的子类变量当作一种数据类型来对待

    多态的方法调用m.toString();//JVM会自动利用instanceof进行点运算符的动态绑定,从而可以区分不同子类之间的差异性

    1 FacultyMember[] members = new FacultyMember [8];
    2 for (int index = 0; index<members.length; index++){
    3     System.out.println(members[index].toString());
    4 }

    [4]“1对多”关联关系的实现

      加<>, <>内为变量名,多个变量间用","间隔;泛型类内的数据类型、构造函数形参类型等均可待定,用<>内的变量表示即可;在声明泛型对象时,数据类型要具体化

      如何撰写一个泛型类:

        1)先写出一个实际的类;

        2)将此类中准备改变的类型名(如应用时,可能int要改变为float或char);即改用一个自己指定泛型参数(如E、A、B);

        3)类中的方法可以使用泛型参数类型,static方法无法访问泛型类的类型参(因为具体的参数类型在实例化的时候才知道)

        4)使用泛型类时,必须在创建对象的时候指定类型参数的值;

      方法也可以声明为泛型方法:

        1)调用泛型方法与调用普通方法一样,不必指明参数类型;

        2)泛型方法可以看作被无限次重载过;

     1 public class GenericMethods{
     2     public <T> void f(T x){
     3         System.out.println(x.toString());
     4     }
     5     
     6     public static void main(String[] args){
     7         genericMethods gn = new GenericMethods();
     8         gn.f("Hello");
     9         gn.f(new Product("coffee", 27, "34"));
    10         gn.f(new Point2D(23, 45));
    11     }
    12 }

     Arrays:管理对象个数确定

      一维数组

      多维数组:java中并没有真正的多维数组,只有数组的数组,java中多维数组不一定是规则的矩阵形式;

             每一行的大小可以单独定义如,int[][] xx;

                         xx[0] = new int[3];

                         xx[1] = new int[2];

    容器类:管理对象个数不确定

      Collection<E>:其内每个位置仅持有一个元素,提供add();方法添加元素,包括

              List<E>:以特定次序存储一组元素; ArrayList<E>,Vector<E>

              Set<E>:元素不得重复

      Map<K, V>:其内每个位置所持有的时一群成对的key-value(键值-实值对),类似小型数据库,提供put();方法添加元素

    1 ArrayList<String> list = new ArrayList<String>();
    2     list.add("ArrayList");
    3     list.add("and");
    4     list.add("for-each");
    5     String result = "";
    6     for(String element : list){
    7         result +=element;
    8     }
    9     stdOut.println(result);
    1 Collection<Point2D> c;
    2 for(Point2D point : c){
    3     int x = point.getX();
    4 }
    5 //c为容器类型的变量,容器的名称
    6 //Point2D为容器内的变量类型
    7 //point为Point2D类型的变量,每次循环的执行都从容器中取出对象并赋给该变量来运用

    [5]基类的重新考虑——继承与接口

    基态类型的变量都是多态的;通过基态变量+“.”运算符激活的基态方法都是多态的,JVM会自动地动态绑定方法地调用和方法地方法体之间的关联关系;

    抽象类存在的原因:

      1)让客户端程序员无法产生(new一个)其对象,并因此确保这只是一个“接口”而无实体;//与非抽象基类的差异

      2)共同的函数特征建立了一个基本形式,让程序员可以陈述所有子类的共同点,任何子类都可以以不同的方法体来表现此一共同的函数特征;

    接口是一个"pure"抽象类:

      1)接口内的所有变量都默认为是public static final的;接口类型不存在构造方法;接口内所有的方法都是static、public的;

      2)架构设计时,如何使用抽象类和接口来解决问题,是一个非常复杂的问题,抽象类更侧重于归纳同一父类的子类的共同特征,如果属性,方法;接口更侧重于定义任意的类有没有相同语义的方法,它是一个一经定义不轻易更改的规范,它的修改在项目中,往往是动一发而牵全身,即使有考虑不周到的地方,也会使用新增接口的形式去弥补。其实abstract class表示的是"is-a"关系,interface表示的是"like-a"关系。最顶级的是接口,然后是抽象类实现接口,最后才到具体类实现。

      1)使用接口,能够实现子型别被向上转型至多个基类型别;

      2)让客户端程序员无法产生其对象,并因此确保这知识一个“接口”而无实体;

      3)共同的接口建立了一个基本形式,让程序员可以陈述所有的实现该接口的子型别的共同点。任何子型别都可以以不同的方法体来表现此共同接口,相比抽象类,“多态”程度更高;

  • 相关阅读:
    gnome3 修改桌面背景图片模式
    记录openSUSE 源码安装node.js
    [转]gnome环境中将家目录下预设的文件夹由中文名称改为英文名称
    Clover config.plist Boot部分
    bootstrap table 实现固定悬浮table 表头并可以水平滚动
    openSUSE 安装compass,mkmf.rb can't find,checking for ffi.h...extconf.rb failed
    读《深入PHP 面向对象、模式与实践》笔记
    openSUSE中启用apache mod_rewrite
    openSUSE安装Composer
    openSUSE 安装LAMP记录
  • 原文地址:https://www.cnblogs.com/li7anStrugglePath/p/12772974.html
Copyright © 2011-2022 走看看