Java基础-011-Java 对象与类

Java基础-011-Java 对象与类


面向对象程序设计概述


 面向对象程序设计(简称 OOP) 是当今主流的程序设计范型, 它已经取代了 20 世纪 70 年代的“ 结构化” 过程化程序设计开发技术。Java 是完全面向对象的。
 面向对象的程序是由对象组成的, 每个对象包含对用户公开的特定功能部分和隐藏的实现部分。程序中的很多对象来自标准库,还有一些是自定义的。在 OOP 中, 不必关心对象的具体实现, 只要能够满足用户的需求即可。

1.类


类(class) 是构造对象的模板或蓝图。 我们可以将类想象成制作小甜饼的切割机,将对象想象为小甜饼。 由类构造 (construct) 对象的过程称为创建类的实例 (instance)。
封装(encapsulation , 有时称为数据隐藏) 是与对象有关的一个重要概念。 从形式上看,封装不过是将数据和行为组合在一个包中, 并对对象的使用者隐藏了数据的实现方式。
 OOP 的另一个原则会让用户自定义 Java 类变得轻而易举, 这就是: 可以通过扩展一个类来建立另外一个新的类。事实上, 在 Java 中, 所有的类都源自于一个“ 神通广大的超类”,它就是 Object。通过扩展一个类来建立另外一个类的过程称为继承(inheritance)

2.对象


要想使用 OOP, —定要清楚对象的三个主要特性:

  • 对象的行为(behavior) — 可以对对象施加哪些操作,或可以对对象施加哪些方法?
  • 对象的状态 (state) — 当施加那些方法时,对象如何响应?
  • 对象标识(identity) — 如何辨别具有相同行为与状态的不同对象?

 同一个类的所有对象实例, 由于支持相同的行为而具有家族式的相似性。对象的行为是用可调用的方法定义的。
 此外,每个对象都保存着描述当前特征的信息。这就是对象的状态。对象的状态可能会随着时间而发生改变,但这种改变不会是自发的。 对象状态的改变必须通过调用方法实现 (如果不经过方法调用就可以改变对象状态, 只能说明封装性遭到了破坏)。
 但是,对象的状态并不能完全描述一个对象。每个对象都有一个唯一的身份(identity)。

3.识别类


 传统的过程化程序设计, 必须从顶部的 main 函数开始编写程序。在面向对象程序设计时没有所谓的“ 顶部”。对于学习OOP 的初学者来说常常会感觉无从下手。答案是:首先从设计类开始,然后再往每个类中添加方法。
 识别类的简单规则是在分析问题的过程中寻找名词,而方法对应着动词。

4.类之间的关系


在类之间, 最常见的关系有

  • 依赖 (“ uses-a”)
  • 聚合(“ has-a”)
  • 继承(“ is-a”)

依赖(dependence ), 即“ uses-a” 关系, 是一种最明显的、 最常见的关系。例如, Order 类使用 Account 类是因为 Order 对象需要访问 Account 对象查看信用状态。但是 Item 类不依赖于 Account 类, 这是因为 Item 对象与客户账户无关。因此, 如果一个类的方法操纵另一个类的对象,我们就说一个类依赖于另一个类。
 应该尽可能地将相互依赖的类减至最少。 如果类 A 不知道 B 的存在, 它就不会关心 B 的任何改变(这意味着 B 的改变不会导致 A 产生任何 bug )。用软件工程的术语来说, 就是让类之间的耦合度最小。
聚合(aggregation ), 即“ has-a” 关系, 是一种具体且易于理解的关系。 例如, 一个 Order 对象包含一些 Item 对象。聚合关系意味着类 A 的对象包含类 B 的对象。
继承(inheritance ), 即“ is-a” 关系, 是一种用于表示特殊与一般关系的。 例如, Rush Order 类由 Order 类继承而来。 在具有特殊性的 RushOrder 类中包含了一些用于优先处理的特殊方法, 以及一个计算运费的不同方法;而其他的方法, 如添加商品、 生成账单等都是从Order 类继承来的。一般而言, 如果类 A 扩展类 B, 类 A 不但包含从类 B 继承的方法,还会拥有一些额外的功能(下一章将详细讨论继承,其中会用较多的篇幅讲述这个重要的概念)。
UML建模

使用预定义类


  在 Java 中, 没有类就无法做任何事情, 我们前面曾经接触过几个类。然而,并不是所有的类都具有面向对象特征。 例如,Math 类。在程序中,可以使用 Math 类的方法, 如 Math.random, 并只需要知道方法名和参数 (如果有的话) ,而不必了解它的具体实现过程。这正是封装的关键所在,当然所有类都是这样。但遗憾的是, Math 类只封装了功能,它不需要也不必隐藏数据。 由于没有数据,因此也不必担心生成对象以及初始化实例域。

1.对象与对象变量

  要想使用对象,就必须首先构造对象, 并指定其初始状态。然后,对对象应用方法。
  在 Java 程序设计语言中, 使用构造器(constructor) 构造新实例。 构造器是一种特殊的方法, 用来构造并初始化对象。

 在标准 Java 库中包含一个 Date 类。它的对象将描述一个时间点, 例如:“ December 31, 1999, 23:59:59 GMT”。
 构造器的名字应该与类名相同。因此 Date 类的构造器名为 Date。要想构造一个 Date 对象, 需要在构造器前面加上 new 操作符,如下所示:

new Date()

这个表达式构造了一个新对象。 这个对象被初始化为当前的日期和时间。
 如果需要的话, 也可以将这个对象传递给一个方法:

System.out.printTn(new DateO) ;

 或者, 也可以将一个方法应用于刚刚创建的对象。Date 类中有一个 toString 方法。 这个方法将返回日期的字符串描述。下面的语句可以说明如何将 toString 方法应用于新构造的 Date 对象上。

String s = new Date().toString();

 在这两个例子中, 构造的对象仅使用了一次。 通常, 希望构造的对象可以多次使用, 因
此,需要将对象存放在一个变量中:

Date birthday = new Date();

在这里插入图片描述

2.Java 类库中的 LocalDate 类


  在前面的例子中, 已经使用了 Java 标准类库中的 Date 类。Date 类的实例有一个状态,即特定的时间点。
  尽管在使用 Date 类时不必知道这一点,但时间是用距离一个固定时间点的毫秒数(可正可负)表示的, 这个点就是所谓的纪元(epoch), 它 是 UTC 时间 1970 年 1 月 1 日 00:00:00。UTC 是 Coordinated Universal Time 的缩写,与大家熟悉的 GMT (即 Greenwich Mean Time, 格林威治时间)一样,是一种具有实践意义的科学标准时间。
  但是, Date 类所提供的日期处理并没有太大的用途。Java 类库的设计者认为: 像 “December 31, 1999, 23:59:59” 这样的日期表示法只是阳历的固有习惯。 这种特定的描述法遵循了世界上大多数地区使用的 Gregorian 阳历表示法。但是, 同一时间点采用中国的农历表示和采用希伯来的阴历表示就很不一样,对于火星历来说就更不可想象了。
  类库设计者决定将保存时间与给时间点命名分开。所以标准 Java 类库分别包含了两个类:一个是用来表示时间点的 Date 类;另一个是用来表示大家熟悉的日历表示法的 LocalDate 类。Java SE 8弓丨入了另外一些类来处理日期和时间的不同方面。
  将时间与日历分开是一种很好的面向对象设计。通常,最好使用不同的类表示不同的概念。
  不要使用构造器来构造 LocalDate 类的对象。实际上,应当使用静态工厂方法 (factory method) 代表你调用构造器。下面的表达式 Local Date.now()会构造一个新对象, 表示构造这个对象时的日期。

public static void main(String[] args) {
    
    
    LocalDate date = LocalDate.now();
    System.out.println(date);
    LocalDate thousandDaysLater = date.plusDays(1000);
    System.out.println(thousandDaysLater);

    int month = date.getMonthValue();
    int today = date.getDayOfMonth();
    date = date.minusDays(today - 1); // Set to start of month
    DayOfWeek weekday = date.getDayOfWeek();
    int value = weekday.getValue(); // 1 = Monday, .. . 7 = Sunday
    System.out.println("Mon Tue Wed Thu Fri Sat Sun");
    for (int i = 1; i < value; i++)
        System.out.print("    ");

    while (date.getMonthValue() == month) {
    
    
        System.out.printf("%3d", date.getDayOfMonth());
        if (date.getDayOfMonth() == today) {
    
    
            System.out.print("*"); // today
        } else {
    
    
            System.out.print(" ");
        }
        date = date.plusDays(1);
        if (date.getDayOfWeek().getValue() == 1) System.out.println();
    }
}

在这里插入图片描述

用户自定义类


就是自己点定义一个class:Employee

public class Employee {
    
    
    private String name;
    private int age;
    private String position;

    Employee() {
    
    
    }

    Employee(String name, int age, String position) {
    
    
        this.name = name;
        this.age = age;
        this.position = position;
    }

    public String getName() {
    
    
        return name;
    }

    public void setAge(int age) {
    
    
        this.age = age;
    }

    public void setPosition(String position) {
    
    
        this.position = position;
    }

    @Override
    public String toString() {
    
    
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", position='" + position + '\'' +
                '}';
    }
}

System.out.println(new Employee("XhBruce", 18, "Android").toString());
在这里插入图片描述

静态域与静态方法


1、静态域

如果将域定义为 static, 每个类中只有一个这样的域。而每一个对象对于所有的实例域却都有自己的一份拷贝。

2、静态常量

静态变量使用得比较少,但静态常量却使用得比较多。例如, 在 Math 类中定义了一个静态常量:Math.PI
在这里插入图片描述

3、静态方法

静态方法是一种不能向对象实施操作的方法。例如,Math 的 pow 方法就是一个静态方法。
Math.pow(x, a)计算 X a X^a Xa

4、工厂方法

静态方法还有另外一种常见的用途。类似 LocalDate 和 NumberFormat 的类使用静态工厂方法 (factory method 来构造对象。 你已经见过工厂方法 LocalDate.now 和 LocalDate.of。
NumberFormat 类如下使用工厂方法生成不同风格的格式化对象:

NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance();
NumberFormat percentFormatter = NumberFormat.getPercentInstance();
double x = 0.1;
System.out.println(currencyFormatter.format(x)); // prints $O.10
System.out.println(percentFormatter.format(x)); // prints 10%

5、main方法

需要注意, 不需要使用对象调用静态方法。例如,不需要构造 Math 类对象就可以调用Math.pow。
同理, main 方法也是一个静态方法。

public class Application {
    
    
	public static void main(StringD args) {
    
    
		// construct objects here
	}
}

main 方法不对任何对象进行操作。事实上,在启动程序时还没有任何一个对象。静态的 main 方法将执行并创建程序所需要的对象。

猜你喜欢

转载自blog.csdn.net/qq_23452385/article/details/110102686