面向对象程序设计概述

面向对象的程序设计(简称OOP)时当今主流的程序设计范型,已经取代了“结构化”过程化程序设计开发技术,Java是完全面向对象的。


设计构造对象的模板或蓝图,由类构造对象的过程称为创建类的实例。

封装(
有时称为数据隐藏)是与对象有关的一个重要概念,从形式上看,封装不过是将数据行为组合在一个包中,并对对象的使用者隐藏了数据的实现方式,封装给对象赋予了“黑盒”特征,这是提高重用性和可靠性的关键。

对象

对象的三个主要特征:

1.对象的行为:可以对对象施加哪些操作,或者可以对对象施加哪些方法?

2.对象的状态:当施加那些方法时,对象如何响应?

3.对象的标识:如何辨别具有相同行为与状态的不同对象?

同一个类的所有对象实例,由于支持相同的行为而具有家族式的相似性,对象的行为是用可调用的方法定义的。

方法:
在Java中,方法就是用来完成解决某件事情或实现某个功能的办法。

类之间的关系

在类之间,最常见的关系如下:

1.依赖:即“uses-a”关系,是一种最明显的/最常见的关系。如果类B的方法操纵类A的对象,则说类B依赖于类A。

2.聚合(也叫关联):即“has-a”关系,是一种易于理解的关系。如果类B的对象包含类A的对象,则意味着聚合关系。

3.继承:即“is-a”关系,是一种用于表示特殊与一般的关系的。  如果类B扩展类A,类B不但包含从类A继承的方法,还可以拥有很多自定义的额外功能。

预定义类

预定义类,就是指JDK中或者其他的jar包中已经定义好可以直接使用的类(如:String类,Math类,Date类,Arrays类等)。

在Java中,没有类就无法做任何事情。

对象与对象变量

要想使用对象,就必须先构造对象,并指定其初始状态,然后对对象应用方法。

在Java程序设计语言中,使用构造器构造新实例,构造器是一种特殊的方法,用来构造并初始化对象。

构造器具有以下特征:

1.构造器与类同名。

2.每个类可以有一个以上的构造器。

3.构造器可以有0个、1个或多个参数。

4.构造器没有返回值。

5.构造器总是伴随着new操作一起调用。

以Date类为例,其构造器名为Date,想要构造一个Date对象,需要在构造器前面加上new操作符:

  1 new Date();

这个对象被初始化为当前的日期和时间。

如果需要的化,这个对象也可以作为一个参数传递给一个方法:

  1 System.out.println(new Date());

也可以将一个方法应用与这个对象,Date类中有一个toString方法:

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

当希望构造的对象可以多次使用时,可以将对象存放在一个变量中:

  1 Date date = new Date();

注意:

一个对象变量并没有实际包含一个对象,而仅仅引用一个对象。

在Java中,任何对象变量的值都是对存储在另一个地方的一个对象的引用。new操作符的返回值也是一个引用。

  1 Date date;

声明了一个Date类型的date变量,现在date作为一个对象变量,可以引用Date类型的对象,但其本身不是一个对象,也没有引用对象。此时不能将任何Date方法应用于这个变量上。

  1 Date date;
2 String str = a.toString();

将会产生编译错误。

必须首先从初始化变量date,才能使用toString方法:

  1 Date date = new Date();
2 String str = a.toString();

用户自定义类

用户自己创建的类,按照类的定义标准,可以在类中包含多个方法与属性,来供用户使用。

Java代码映射成现实事物的过程就是定义类的过程。

类的定义格式:

创建java文件,与类名相同:

  1 public class 类名{
2 数据类型 属性名称1;
3 数据类型 属性名称2;
4 …
5 }

例如:创建一个名为Employee的类:

  1 public class Employee {
2 private String name;
3 private double salary;
4
5 public Employee(String n, double s){
6 name = n;
7 salary = s;
8 }
9
10 public String getName(){
11 return name;
12 }
13 public void setName(String name) {
14 this.name = name;
15 }
16
17 public double getSalary(){
18 return salary;
19 }
20 public void setSalary(double salary) {
21 this.salary = salary;
22 }
23
24 public void raiseSalary(double byPercent){
25 double raise = salary * byPercent / 100;
26 salary += raise;
27 }
28 }

这里自定义创建了的Employee类,包含name和salary两个域(属性),Employee()和raiseSalary()两个方法,其中Employee()方法为构造方法。

注意:

raiseSalary()方法有两个参数。

第一个参数称为隐式参数,是出现在方法名前的Employee类对象。

如下程序所示,关键字this表示隐式参数。

  1 public void raiseSalary(double byPercent){
2 double raise = this.salary * byPercent / 100;
3 this.salary += raise;
4 }

第二个参数位于方法名后面括号中的数值(double byPercent),这是一个显式参数。

程序中getName()和getSalary()方法为访问器方法,setName()和setSalary()方法为更改器方法。

通过private私有化域name,在通过访问器方法和更改其方法进行访问和更改域值的方式,就是简单的封装了。

final实例域

可以将实例域定义为final,构建对象时必须初始化这样的域。

必须确保在每一个构造器执行后,这个域的值被设置,并且在后面的操作中,不能再对它进行修改。

final修饰符大都应用于**基本**类型域,或**不可变类**的域。(如果类中的每个方法都不会改变其对象,这种类就是不可变类,例如:String类。)

  1 class Employee {
2 private final String name;
3
4 public String getName(){
5 return name;
6 }
7 }

将Employee类中的name域声明为final,这样在对象构建之后,这个值不会再被修改,即没有setName()方法。

静态域与静态方法(static)

静态域

  1 class Employee {
2 private static int stacId = 1
3 private int id;
4 }

类中将stacId定义为static,那么这个类的所有的实例将共享一个static域stacId,即使一个实例对象都没有,这个静态域仍然存在。

但是如果这个类有2个实例对象,则有2个实例域id。

静态方法

静态方法是一种不能向对象实施操作的方法,可以认为静态方法是没有this参数的方法。

  1 class Employee {
2 private static int stacId = 1
3 private int id;
4
5 public static int getStacId(){
6 return stacId;
7 }
8 }

静态方法getStacId 不能访问id实例域,因为它不能操作对象,但是可以访问自身类中的静态域。

对象构造

重载

Java允许在一个类中定义多个名称相同的方法,但是参数的类型或个数必须不同,这就是方法的重载

程序有可能针对各种(例如同类运算:加法)不同种情况(2个数相加、3个数相加)都各自定义一个方法,如果每个方法的名称都不相同,在调用时就很难分清哪种情况该调用哪个方法,重载存在的意义就是解决这个问题,使用相同的方法名对各种不同情况做处理。

默认域的初始化

如果再构造器中没有显式的给域赋予初值,那么就会被自动的赋予为默认值(数值型为0,布尔型为false,对象引用为null)。

无参数的构造器

很多类都包含一个无参数的构造器,对象由无参数构造器创建时,其状态会设置为适当的默认值(即构造器中初始化的值)。

若编写一个类时,没有编写构造器,那么系统就会提供一个无参数构造器。这个构造器将所有的实例域设置为默认值(数值型数据设置为0,布尔型数据设置为false,所有对象变量设置为null)。

若类中提供了至少一个构造器,但是没有提供无参数的构造器,则在构造对象时如果没有提供参数就会被视为不合法,将会产生错误。

参数名

首先是参数的命名问题。

  1 public Employee(String n, double s){
2 name = n;
3 salary = s;
4 }

这样做有一个缺陷,只有阅读代码才能了解参数n和s的含义。

有两种方式避免这个问题:

1.在每个参数前面加一个“a”:

  1 public Employee(String aName, double aSalary){
2 name = aName;
3 salary = aSalary;
4 }

2.基于这样的事实:参数变量用同样的名字将实例域屏蔽起来,但是可以采用this.xxx的形式:

  1 public Employee(String name, double salary){
2 this.name = name;
3 this.salary = salary;
4 }

调用另一个构造器

关键字“this”引用方法的隐式参数,但是它还有另一个含义。

若构造器的第一个语句形如this(...),这个构造器将调用同一个类的另一个构造器。

  1 public class Employee {
2 private String name;
3 private double salary;
4 private static int stacId = 1;
5
6 public Employee(String name, double salary){
7 this.name = name;
8 this.salary = salary;
9 }
10
11 public Employee(double salary){
12 this("Employee #" + stacId, salary);
13 stacId++;
14 }
15
16 public String getName(){
17 return name;
18 }
19 public void setName(String name) {
20 this.name = name;
21 }
22
23 public double getSalary(){
24 return salary;
25 }
26 public void setSalary(double salary) {
27 this.salary = salary;
28 }
29
30 public void raiseSalary(double byPercent){
31 double raise = this.salary * byPercent / 100;
32 this.salary += raise;
33 }
34 }

创建一个测试;Employee类的测试类:

  1 public class EmployeeTest {
2 public static void main(String[] args){
3 Employee employee = new Employee(100);
4 }
5 }

通过debug可以看到Employee(double)构造器将调用Employee(String,double)构造器,这样使用this关键字非常有用,对公共的构造器代码部分只需要编写一次即可。

使用包的主要原因时确保类名的唯一性。

类的导入


一个类可以使用所属包中的所有类,以及其他包中的公有类(public class)。

访问另一个包中的共有类有2中方式:

1.在每个类名之前添加完整的包名。

  1 java.time.LocalDate today = java.time.LocalDate.now();

这显然很繁琐。

2.使用import语句。

可以使用import语句导入一个特定的类或者整个包。import语句应该位于源文件的顶部(但是位于package语句的而后面)。

注释位置


类注释
必须放在import语句之后,类定义之前。

方法注释
必须放在所描述的方法之前。

域注释
通常只需对公有域(静态常量)进行注释。

类设计技巧

可以使得设计出来的类更具有OOP专业水准的几点技巧:

1.一定要保证数据私有。这是最重要的,绝对不要破坏封装性。

2.一定要对数据初始化。Java不对局部变量进行初始化,但是会对对象的实例域进行初始化。最好不要依赖于系统的默认值,而是应该显式的初始化所有的数据,具体的初始化方式可以是提供默认值,也可以是在所有构造器中设置默认值。

3.不要在类中使用过多的基本类型。可以根据基本类型特点自定义类进行使用。

4.不是所有的域都需要独立的域访问器和域更改器。

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

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

7.优先使用不可变的类。

Java基础-对象与类的更多相关文章

  1. 一天一个Java基础——对象和类

    1.在Java中你所做的全部工作就是定义类,产生那些类的对象,以及发送消息给这些对象 2.可以在类中设置两种类型的元素:字段(也被称作数据成员)和方法(也被称作成员函数) 3.字段可以是任何类型的对象 ...

  2. Java基础——对象和类

    将包含main方法的类称为主类. 变量的作用域是指变量可以在程序中引用的范围. 实例变量和静态变量的作用域是整个类,无论变量是在哪里声明的. 局部变量的声明和使用都在一个方法的内部. 一个类的实例变量 ...

  3. Java基础-DButils工具类(QueryRunner)详解

    Java基础-DButils工具类(QueryRunner)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 如果只使用JDBC进行开发,我们会发现冗余代码过多,为了简化JDBC ...

  4. Java基础之File类的使用

    Java基础之File类的使用 1.File类的构造方法和常用方法 2.对File中listFile(FileNameFilter name)学习 3.与File文件类相关的实现 File类的构造方法 ...

  5. Java常见对象Object类中的个别方法

    Java常见对象Object类 public int hashCode() : 返回该对象的哈希码值. 注意:哈希值是根据哈希算法计算出来的一个值,这个值和地址值有关,但是不是实际地址值.你可以理解成 ...

  6. 快乐编程大本营【java语言训练班】 6课:用java的对象和类编程

    快乐编程大本营[java语言训练班] 6课:用java的对象和类编程 第1节. 什么是对象和类 第2节. 对象的属性和方法 第3节. 类的继承 第4节. 使用举例:创建类,定义方法,定义属性 第5节. ...

  7. Java的对象与类,继承

    Java的对象与类,继承 题目1.Java类的建立与使用 设计一个用来描述汽车的类,使用类的非静态成员变量来表示汽车的车主姓名.当前的速率和当前方向盘的转向角度,使用类的非静态成员方法来表示改变汽车的 ...

  8. 《java基础——对象的拷贝》

    java基础--对象的拷贝 一.浅拷贝: 规则: 1. 浅拷贝只是拷贝了源对象的地址,所以源对象的值发生变化时,拷贝对象的值也会发生变化. 2. 浅拷贝相当于两个对象共用一套实例. 格式: 类名 对象 ...

  9. 你真的了解JAVA中对象和类、this、super和static关键字吗

    作者:小牛呼噜噜 | https://xiaoniuhululu.com 计算机内功.JAVA底层.面试相关资料等更多精彩文章在公众号「小牛呼噜噜 」 目录 Java对象究竟是什么? 创建对象的过程 ...

随机推荐

  1. codeforces 1151 B

    codeforces 1151  B codeforces 1151  B  1600fen 题意:n*m的矩阵,问能否从n行中每行选一个数 异或 大于0 解析:刚开始看没思路,想用dfs跑一遍,看到 ...

  2. [Kubernetes]资源模型与资源管理

    作为 Kubernetes 的资源管理与调度部分的基础,需要从它的资源模型说起. 资源管理模型的设计 我们知道,在 Kubernetes 里面, Pod 是最小的原子调度单位,这就意味着,所有和调度和 ...

  3. input子系统学习笔记六 按键驱动实例分析下【转】

    转自:http://blog.chinaunix.net/uid-20776117-id-3212095.html 本文接着input子系统学习笔记五 按键驱动实例分析上接续分析这个按键驱动实例! i ...

  4. ABP代码生成器与升级到VS2017VSIX

    首先,我不是要分享一个代码生成器,而是怎么升级到VS2017,简单介绍下 如何将2015的VSIX项目升级到2017 阳光铭睿 写了一篇<分享一个与ABP配套使用的代码生成器源码>,并在群 ...

  5. 02使用java脚本向Pxc集群写入数据

    使用java脚本向Pxc集群写入数据 批量写入pxc集群程序 导入mysql驱动包 # 批量插入数据的java脚本 package pxc_demo; import java.sql.Connecti ...

  6. Salesforce知识整理(一)之Lightning Web Component Tools

    目录 LWC知识整理(一) 工具 Salesforce CLI Visual Studio Code(VS Code) Developer Hub(Dev Hub) 开启Dev Hub 相关资料 茶余 ...

  7. Java数组的声明和遍历

    Java 数组 数组对于每一门编程语言来说都是重要的数据结构之一,当然不同语言对数组的实现及处理也不尽相同. Java 语言中提供的数组是用来存储固定大小的同类型元素. 你可以声明一个数组变量,如 n ...

  8. mysqldump命令使用

    1.执行mysqldump命令前,先给配制添加帐号和密码: # vi /etc/my.cnf user=root password=XXXXXX 2. # mysqldump -uroot -pXXX ...

  9. 生活日历NABCD需求分析

    这次我们团队要开发一个生活日历APP,对于这个APP的NABCD的需求分析,我对此作出其中的一小部分介绍. N(Need)需求 目前市场上有很多的日历程序,每个手机自带的功能中必然有日历程序.但是对于 ...

  10. golang 使用pprof进行性能调优

    package main import "fmt" func lengthOfNonRepeatingSubStr(s string) int { lastOccurred := ...