面向对象程序设计概述

面向对象的程序设计(简称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. 编写MyCP.java 实现类似Linux下cp XXX1 XXX2的功能

    题目:编写MyCP.java 实现类似Linux下cp XXX1 XXX2的功能 要求:MyCP支持两个参数: java MyCP -tx XXX1.txt XXX2.bin 用来把文本文件(内容为十 ...

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

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

  3. Gitlab_ansible_jenkins三剑客⑤jenkins Pipeline-job的使用

    Pipeline-job的使用 创建Pipeline任务 找到root用户的id 编写pipeline脚本 #!groovy pipeline{ agent {node {label 'master' ...

  4. scikit-learn中机器学习模型比较(逻辑回归与KNN)

    本文源自于Kevin Markham 的模型评估:https://github.com/justmarkham/scikit-learn-videos/blob/master/05_model_eva ...

  5. TopN案例

    准备三份数据 t1 2067 t2 2055 t3 2055 t4 1200 t5 2367 t6 255 t7 2555 t8 12100 t9 20647 t10 245 t11 205 t12 ...

  6. css 自制一些小特效

    Github地址 位于gh-pages分支上 https://github.com/a1115040996/MyHTML/ 3D 卡片特效 地址: https://a1115040996.github ...

  7. 白话大数据 | Spark和Hadoop到底谁更厉害?

    要想搞清楚spark跟Hadoop到底谁更厉害,首先得明白spark到底是什么鬼. 经过之前的介绍大家应该非常了解什么是Hadoop了(不了解的点击这里:白话大数据 | hadoop究竟是什么鬼),简 ...

  8. linux系统优化配置

    # 2 millions system-wide sysctl -w fs.file-max=2097152 sysctl -w fs.nr_open=2097152 echo 2097152 > ...

  9. Excel—图表函数

    OFFSET(引用函数)它可以找一个区域,把一个区域的值都拿回来 函数语法:OFFSET(从哪个单元格开始,这个单元格下移多少行开始,然后现在的位置再往右多少列开始,要取的值是现在的位置开始下移多少行 ...

  10. python默认参数陷阱

    对于学习python的人都有这样的困惑 def foo(a=[]): a.append(5) return a Python新手希望这个函数总是返回一个只包含一个元素的列表:[5].结果却非常不同,而 ...