转载

Java Core.四.对象与类

四.对象与类

4.1 面向对象程序设计概述

4.1.4 类之间的关系

  • 分类:依赖(uses a),聚合(has a),继承(is a)
  • 依赖

    • 一个类的方法操纵另一个类的对象
    • 最常见的关系,最明显的关系
    • 设计中应该遵循尽可能减少依赖,依赖越低,耦合越低
  • 聚合

    • 一个类中包含着另一个类

4.2 使用预定义类

4.2.1 对象与对象变量

1.对象变量

  • 定义:引用变量的部分
  • 注意

    • 一个对象变量不包含对象,仅仅引用一个对象

4.3 用户自定义类

4.3.4 构造器

  • 规则

    • 构造器与类同名
    • 每个类可以有一个及以上的构造器
    • 构造器可以有0至多个参数
    • 构造器没有返回值
    • 构造器随着new操作符的执行被调用,无法通过构造器重新设置实例域

4.3.5 隐式参数与显式参数

  • 隐式参数:方法名面前的类对象,使用this关键字代表
  • 显式参数:传入方法的参数

    <!--实现-->

    public void raise(double ByPercent){
      double raise = this.salary * ByPercent;
    }
    /* conclusion
    1.ByPercent为显式参数
    2.this为隐式参数,代表类对象
    */

4.3.6 封装的优点

1.域访问器

  • 定义:返回实例域值的机器
  • 组成

    • 私有数据域
    • 公有的域访问器方法
    • 公有的域更改器方法
  • 格式:public修饰,返回值为实例域值

    <!--实现-->

    // 需求:返回薪水值
    public class Worker{
      private int salary;
    }
    // 域访问器
    public int getSalary(){
      return salary;
    }
  • 优势

    • 支持修改内部实现,不影响其他代码
    • 支持执行错误检查 <!--比如判断传入数据是否为空-->
  • 注意

    • 如果需要返回一个可变数据域的拷贝,使用clone()

      <!--实现-->

      class E{
          ...
          public Date getH(){
          return (Date)hire.clone();
        }
      }

4.4 静态域和静态方法

4.4.1 静态域

  • 定义:被static修饰的域
  • 特点:静态域属于类,不属于对象。 也就是所有对象共享一个静态域

4.4.2 静态常量

  • 常用的静态常量

    • Math.PI

      <!--实现-->

      // 定义
      public class Math {
          public static final double PI = 3.123453454354535345;
      }
      // 使用
      public class TestMath {
          public static void main(String[] args) {
              int l = 5;
              double circle = l*l*Math.PI;
              System.out.println(circle);
          }
      }
    • System.out

4.4.3 静态方法

  • 定义:不能向对象实施操作的方法 (静态方法是没有this参数的方法)
  • 使用场景

    • 方法不需要访问对象状态,所需参数都是通过显示参数提供 <!--比如Math.pow-->
    • 方法只需要访问类的静态域 <!--比如返回静态域内容的get方法-->

4.4.4 工厂方法

  • 定义:静态方法模式,支持返回预期的对象
  • 步骤

    • 创建抽象产品类,定义公共的接口 <!--需要获得工厂中多种对象,返回方法的变量类型能够统一-->
    • 创建具体产品类
    • 创建工厂类,创建静态方法来返回具体产品类
    • 外部类调用工厂类中的静态方法获得相应的产品对象

      <!--实现-->

      // 抽象产品类,方便产生多种产品类型
      abstract class Product {
          protected abstract void show();
      }
      // 具体产品类1
      public class Product1 extends Product {
          @Override public void show() {
              System.out.println("Product1");
          }
      }
      
      // 具体产品类2
      public class Product2 extends Product {
          @Override public void show() {
              System.out.println("Product2");
          }
      }
      
      // 具体产品类3
      public class Product3 extends Product {
          @Override public void show() {
              System.out.println("Product3");
          }
      }
      // 工厂类,根据传入参数类型返回相应的对象
      public class ProductFatory {
          public static Product getProduct(String s){
              switch (s){
                  default:return null;
                  case "a" :return new Product1();
                  case "b" :return new Product2();
                  case "c" :return new Product3();
              }
          }
      }
      // 测试类
      public class TestFactory {
          public static void main(String[] args) {
              ProductFatory.getProduct("a").show();
              ProductFatory.getProduct("b").show();
              ProductFatory.getProduct("c").show();
          }
      }
      /* output 
      Product1
      Product2
      Product3
      */
  • Pros

    • 创建实例和使用实例解耦
  • Cons

    • 工厂类出现错误时,整个系统受到影响
    • 违背“开放-关闭原则”,新增类需要修改工厂逻辑,工厂类将冗杂

4.5 方法参数

  • 规则:java按值调用,方法得到的是所有参数值的拷贝

    • 无法修改基本数据类型的值。

      <!--实现-->

      // 修改值的方法
      public class Method {
          public void changeNum(int num){
              num = num * 3;
          }
      }
      
      // 测试类
      public class TestMethodParam {
          public static void main(String[] args) {
              int n = 5;
              Method method = new Method();
              System.out.println(n);
              method.changeNum(n);
              System.out.println(n);
          }
      }
      /* output
      5
      5
      */
      
      /* conclusion
      因为num被初始化为n值的拷贝,因此修改num不会影响n的值
      */
    • 支持修改对象参数的状态

      原因:形参是对 对象引用的拷贝,因此指向的是对象,当发生修改时,会修改对象中的值

    • 不支持让对象参数引用一个新的对象

      原因:形参是对象引用的拷贝,修改引用无法对原引用造成影响

      原理图:

      Java Core.四.对象与类

4.6 对象构造

4.6.1 重载

1.方法的签名

  • 格式:方法名以及参数类型

    <!--实现-->

    indexOf(int)

4.6.6 调用另一个构造器

  • 格式:在类中的构造器中使用this关键字调用另一个构造器

    <!--实现-->

    public class TestCons {
        private int age;
        private String name;
    
        private TestCons(int aAge) {
            this.age = aAge;
        }
    
        private TestCons(int aAge , String aName) {
            this(5);
            this.name = aName;
        }
    
        public static void main(String[] args) {
            TestCons testCons = new TestCons(4,"Toyz");
            System.out.println(testCons.age);
            System.out.println(testCons.name);
        }
    }

4.6.7 初始化数据的方法

  • 方法

    1. 在构造器中设置值

      <!--实现-->

      private TestCons(int aAge) {
              this.age = aAge;
          }
    2. 在声明中赋值

      <!--实现-->

      private int age = 5;
    3. 在初始化块中赋值(不常见,通常可以在构造器中实现)

      <!--实现-->

      {
         int age = 5;
      }
  • 执行顺序

    1. 所有数据域初始化为默认值
    2. 根据在类中的声明顺序,执行初始化语句(上述方法2)和初始化域(上述方法3)
    3. 执行构造器(上述方法1)

4.10 类设计技巧

  • 一定要保证数据私有性
  • 一定要对数据初始化
  • 不要在类中使用过多的基本类型(使用其他类来代替)
  • 不是所有域都需要独立的域访问和修改器
  • 对职责过多的类进行分解(不然会导致耦合过高)
  • 类名和方法名能够体现职责
  • 优先使用不可变的类
原文  https://segmentfault.com/a/1190000019961934
正文到此结束
Loading...