0%

Java 类基础

1. 概述

△Java语言就是基于类的语言,许多术语与C++稍有区别

C++Java
函数方法
构造函数构造器
析构函数析构器
类中的数据实例域
静态数据静态域

例如 String a;
C++ 称 String 为类,而 a 为对象,C++ 在此时就分配了内存,构建了对象
Java 称 String 为类,a 为引用,而当使用 new 请求,分配了空间,构建出的数据块称为对象

类对象必须使用new来构建,单纯的声明类仅仅只是声明了类的引用,并没有分配空间

2. 自定义类

  1. 一个源文件只能拥有一个 public 类,且必须与文件名一致

    通过在类的 class 前缀上 public 获得这一特性

    包含 main() 方法的类才能成为启动类,每个类都可以拥有 main()方法
    通常用作类的普通测试

  2. Java不支持析构函数,反之,会自动进行垃圾回收

  3. 所有的方法都要在类的内部进行定义

    实际上,任何一个Java程序都是从类开始的

  4. 如果需要返回一个可变对象的引用,应该对其进行克隆(clone)

    ※这是由于变量都是一个指向对象的“类似指针的”引用,有可能会使得数据封装性遭到破坏

  5. final 修饰符在使用时大多应用于不可修改的类,当应用在可变的类的时候,并不意味着类的内容不可修改

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Employee
    {
    private final String name;
    private final Date hiredate: 2017-03-16
    }

    /**
    * 此时,name引用和对象都不能被修改【String类是不可变的类】
    * hiredate: 2017-03-16
    * 这里的hiredate: 2017-03-16
    */
  6. 通过 static 声明静态域和静态方法

  • 静态域和 C++ 类中的静态变量没有什么区别

  • 静态公有常量可以通过类名来直接调用,由于有 final 限制,所以不会造成封装性破坏

    如Math.PI就是一个静态公有变量

    其实也可以通过对象引用来调用,不过一般通过类名调用使得易读性更强

    静态方法可以通过类名和对象引用直接调用,但一般使用类名调用增强易读性
    如 Math.pow(x,y)

  • 静态方法只能对对象静态域实施操作,而不能对实例域实施操作

  • 通常只有在接受外来参数和调用静态域的时候才使用静态方法

  1. 对象的构造

    1. 可以直接在构造器内初始化实例域,即使是包含关系

    2. 通过使用this来实现传参和实例域同名,甚至调用另一个构造器

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      public Class(String name, double salary)
      {
      this.name = name;
      this.salary = salary;
      }

      public Class(double s)
      {
      this("Class * " + nextId, s);
      nextId++;
      }
    3. 默认将所有数值初始化为0,布尔值初始化为false,引用初始化为null

      如果没有提供显式构造器,则系统自动生成隐式(无参)构造器完成上述工作

      如果提供了显式构造器,则系统将不再自动生成无参构造器,上述操作将被视为非法

    4. 初始化块

      ※这个不常用,通常使用构造器完成工作
      可以使用一个代码块对实例域进行初始化操作

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      class Class
      {
      private int id;
      ....

      {
      id = 1;
      }

      }

      初始化块在所有构造器执行之前执行。
      通过标记关键字static可以对静态域进行初始化块操作

      1
      2
      3
      4
      static
      {
      id = 1;
      }
  2. 类的基本结构

  • 数据域
  • 构造器(constructor)
    • 访问器(getter)
    • 更改器(setter)

3. 方法参数

  1. Java总是按值传参,对象引用也是一个值

  2. 方法不能修改传递给它的实参

  3. 方法可以通过调用传入对象引用的对象的方法,实现对对象的修改

  4. 方法不能让对象参数引用一个新的对象

  5. 方法能够直接访问和修改相同类作为参数的对象实例的私有域

    1
    2
    3
    4
    5
    6
    7
    class Foo {
    private String text;

    public void doStuff(Foo f) {
    System.out.println(f.text);
    }
    }

4. 包(package

※类似于C++的名称空间

  • 通过import语句来导入Java包

  • 添加static指令可以直接导入静态方法和静态域,使用的时候就无需使用类名来调用【UnRecommended】

  • 通过使用包名来具体访问一个类

  • 通过package语句来将类放入包中,通常在开头加入

    1
    package com.myapp.corejava;

    注意包名的命名要与目录树相匹配,即上述类文件必须位于 com/myapp/corejava 中,否则,最终的程序将无法运行

  • 包作用域

    • 如果实例域没有指定访问控制符,则这一个部分可以被同一个包的所有方法访问

      在编写类的时候,必须为实例域添加上访问控制符

  • 类路径(※好像只有使用Shell编译才会遇到这个问题?)

  • javadoc文档注释

    • /** 开头,以 */ 结尾
    • 可以使用 HTML 修饰符
    • 还有各种注释,这里不一一说明

5. 类设计技巧

  1. 保证数据私有

  2. 一定要对数据初始化,可以直接提供默认值,也可以在构造器中提供

  3. 不要在类中使用过多的基本类型,可以通过一个封装类来减少使用

    1
    2
    3
    private String street;
    private String city;
    private String state;

    这个可以通过一个 Address 类来解决

  4. 并不是所有的数据都需要访问器和更改器

  5. 将职责过多的类进行分解

    如果一个类能被拆分成两个或者多个独立的概念,那就进行拆分
    注意这里是概念的拆分,而不是单纯将方法拆分

  6. 类名和方法名要能够体现它们的职责

    类名常用一个名词或者有定语修饰的名词
    访问器使用小写的get开头
    更改器使用小写的set开头

  • 本文作者: Wafer Li
  • 本文链接: https://wafer.li/Java/Java 类基础/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!