Java学习Day02

第4章 对象与类

4.1 面向对象程序设计概述

  1. OOA、OOD、OOP

    OO,Object-Oriented,面向对象。OO方法是一种把面向对象的思想应用于软件开发过程中,指导开发活动的系统方法。

    • OOA,Object-Oriented Analysis,面向对象分析
    • OOD,Object-Oriented Design,面向对象设计
    • OOP,Object-Oriented Programming,面向对象编程
  2. 类是构造对象的模板或蓝图。由类构造对象的过程称为创建类的实例(instance)。

    1. Java方法创建

      方法的定义(方法名首字母小写,驼峰命名法)

      1
      2
      3
      访问修饰符  返回值类型  方法名(){
      方法主体
      }
    2. 类的创建及类与对象的关系

      类的定义(类名首字母大写)

      1
      2
      3
      4
      class 类名称{
      属性;
      方法;
      }

      类与对象的关系:对象是类的实例,类是对象的模板。类是抽象的概念,而对象是具体实例。

      对象的内存划分.png

    3. Java面向对象思想编程

      面向对象三大特性:

      • 封装 对外部不可见
      • 继承 扩展类的功能
      • 多态 1.方法的重载 2.对象的多态性
    4. Java方法递归调用

      eg:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      public static void main(String[] args){
      System.out.println(addNumber(100));
      }
      public static int addNumber(int num){
      if (num == 1){//程序出口
      return 1;
      }else{
      return num+addNumber(num-1);
      }
      }
  3. 对象的三个主要特性:

    • 行为(behavior)——可以对对象施加哪些操作/方法
    • 状态(state)——施加方法时,对象是如何响应的
    • 标识(identity)——如何辨别具有相同行为与状态的不同对象
  4. 类之间的关系

    • 依赖(“uses-a”),如果一个类的方法操纵另一个类的对象,我们就说一个类依赖于另一个类。但这种依赖性应减少。
    • 聚合(“has-a”),聚合关系意味着类A的对象包含着类B的对象。
    • 继承(“is-a”),是一种表示特殊与一般的关系。一般而言,如果类A扩展类B,类A不但包含从类B继承的方法,还会拥有一些额外的功能。

    UML(Unified Modeling Language),统一建模语言,用于绘制类图,用来描述类之间的关系。类用矩形表示,类之间的关系用带有各种修饰符的箭头表示。

4.2 使用预定义类

  1. 对象与对象变量

    • 对象,在构造器前加上new操作符,即可构造出新对象。
    • 一个对象变量,并没有实际包含一个对象,而仅仅引用一个对象。
    • 对象存储在堆内存中,而对象变量也即引用存储在栈内存中。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    public class People {

    String name;
    int age;

    // 构造器(constructor),是一种特殊的方法,又称构造方法
    // 如果自己不重新构造,系统会默认自动生成无参的构造方法;
    // 相反,如果自己写了构造方法,如若需要无参的构造方法,则需手动添加无参的构造方法。
    public People() {

    }

    public People(String name, int age) {
    this.name = name;
    this.age = age;
    }

    public static void main(String[] args) {

    // 此处的chinese只是一个对象变量,既不是对象,也没有引用对象
    People chinese;

    // chinese初始化后,对象变量chinese引用了一个对象,我们也称chinese为“引用”
    // 此处的 new People("张三",22) 构造了新对象,存储在堆内存中
    chinese = new People("张三",22);

    }
    }
  2. Java类库中的Date类、LocalDate类

    • Date类存在问题,很多方法已经被弃置了,不用。

    • LocalDate类,需使用静态工厂方法构造新对象。

      1
           

4.3 用户自定义类

  1. 类的定义(类名首字母大写)

    1
    2
    3
    4
    class 类名称{
    属性;
    方法;
    }
  2. 一个源文件,只能有一个公共类,但可以有任意数目的非公有类。公共类的名称与源文件名称应完全相同。当一个源文件有多个类时,经编译器编译后,会生成多个.class字节码文件。

  3. 构造器

    • 构造器与类同名
    • 每个类可以有一个以上的构造器
    • 构造器可以有0个、1个或多个参数
    • 构造器没有返回值
    • 构造器总是伴随着new操作一起调用
  4. 隐式参数与显示参数

    • 在每一个方法中,关键字this表示隐式参数
    • 位于方法名后面括号中的参数,称为显示参数
  5. 封装性

    1. 目的:保护某些属性和方法不被外部所看见
    2. 封装的实现:
      • 为属性和方法进行封装是通过关键字private声明的
      • 实现该属性的set和get方法,为外部所访问
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    class Person {
    private int age;
    private String name;

    //快捷生成方式:右击->source->Generate Getter and Setter……
    //get方法
    public int getAge() {
    return age;
    }
    //set方法
    public void setAge(int age) {
    if(age>0&&age<150){
    this.age = age;
    }
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }

    public void tell(){
    System.out.println("姓名:"+getName()+" "+"年龄:"+getAge());
    }

    }

    public class Demo01 {

    public static void main(String[] args) {
    Person per = new Person();
    // per.name = "张三";
    // per.age = 30;
    // per.setAge(-30);//最后age结果为0
    per.setAge(30);//设置
    per.setName("张三");
    per.tell();
    //使用 对象.属性/方法 进行使用
    System.out.println("姓名:"+per.getName()+" "+"年龄:"+per.getAge());

    }

    }

  6. final关键字

    • 修饰类。当用final去修饰一个类的时候,表示这个类不能被继承。

      注意:

      • 被final修饰的类,final类中的成员变量可以根据自己的实际需要设计为fianl。
      • final类中的成员方法都会被隐式的指定为final方法。

      在JDK中,被设计为final类的有String、System等。

    • 修饰方法。被final修饰的方法不能被重写。
      注意:

      • 一个类的private方法会隐式的被指定为final方法。
      • 如果父类中有final修饰的方法,那么子类不能去重写。
    • 修饰成员变量。
      注意:

      • 必须初始化值,而且是只能初始化一次。
      • 被fianl修饰的成员变量赋值,有两种方式:1、直接赋值 2、全部在构造方法中赋初值。
      • 如果修饰的成员变量是基本类型,则表示这个变量的值不能改变。
      • 如果修饰的成员变量是一个引用类型,则是说这个引用的地址的值不能修改,但是这个引用所指向的对象里面的内容还是可以改变的。

4.4 静态域与静态方法

  1. 若将域定义为static,则该域为静态域,每个类中只有一个这样的域。静态域属于类,而不属于任何独立的对象。

  2. 静态方法是一种不能面向对象实施操作的方法。也就是说,不需要对象就能调用。

    静态方法不可以调用非静态方法,但非静态方法可以调用静态方法。

    使用静态方法的情况:

    • 一个方法不需要访问对象状态,其所需参数都是通过显示参数提供(例如Math.pow)。
    • 一个方法只需要访问类的静态域。
  3. 工厂方法。

    类似LocalDate和NumberFormat的类使用静态工厂方法来构造对象。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public static void main(String[] args) {

    NumberFormat currencyFormat = NumberFormat.getCurrencyInstance();
    NumberFormat percentFormat = NumberFormat.getPercentInstance();
    double x = 0.111;
    System.out.println(currencyFormat.format(x));
    System.out.println(percentFormat.format(x));

    }

    结果为:

    1
    2
    0.11
    11%

    为什么NumberFormat等类不利用构造器完成这些操作呢?原因如下:

    • 无法命名构造器。构造器的名字必须与类名相同,但是,这里希望将得到的货币实例和百分比实例采用不同的名字。
    • 当使用构造器时,无法改变所构造的对象类型。而Factory方法将返回一个DecimalFormat类对象,这是NumberFormat子类。

4.5 方法参数

  1. Java程序设计语言总是采用按值调用。
  2. 方法参数共有两种类型:
    • 基本数字类型(数字、布尔值)
    • 对象引用

4.6 对象构造

  1. 重载(overloading)。在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同甚至是参数顺序不同)则视为重载。同时,重载对返回类型没有要求,可以相同也可以不同,但不能通过返回类型是否相同来判断重载。

    1
    2
    3
    4
    5
    6
    public void getAge() {
    System.out.println("默认值18");
    }
    public void getAge(int age) {
    System.out.println("年龄:"+age);
    }
  2. 通过关键字“this”,构造器可以调用同一个类的另一个构造器。

  3. 对象析构与finalize方法

    • 由于Java有自动的垃圾回收器,不需要人工回收内存,所以Java不支持析构器。
    • finalize方法会在垃圾回收器清除对象之前调用,回收内存。但尽量不要使用,因为很难知道这个方法什么时候才能够调用。

4.7 包

  1. 使用import语句导入一个特定的类或整个包。import语句要在package语句后面,源文件的顶部。
  2. 关于包的引入,在开发过程中,会有提示,直接引入即可。

4.8 类路径

  1. 类存储在文件系统的子目录中。类的路径必须与包名匹配。
  2. 类也可存储在JAR(Java归档)文件中。

4.9 文档注释

JavaDoc注释,可生成API文档,使用“/** */”。eclipse中的快捷键:打出“/**”,然后回车即可。

具体的注释内的内容,视情况而定。

4.10 类设计技巧

  1. 一定要保证数据私有
  2. 一定要对数据初始化
  3. 不要再类中使用过多的基本类型。也即,用其他的类代替多个相关的基本类型的使用。
  4. 不是所有的域都需要独立的域访问器和域更改器。
  5. 将职责过多的类进行分解
  6. 类名和方法名要能够体现他们的职责
  7. 优先使用不可变的类。如果类是不可变的,就可以安全地在多个线程间共享其对象。