结构化编程

在程序设计的早期,程序用流程图和自顶向下的方法设计。采用这种设计方法,程序员会将一个大的问题分解成更小的任务,然后为每个更小的任务编写一个过程(或函数)。最后,程序员会编写一个主过程来启动程序流程,随后根据程序流程走向,调用想要的其它过程。这种类型的程序设计被称为结构化编程。现在有很多结构化编程语言被广泛使用,最突出的就是C语言。

在结构化编程中,程序围绕着要解决的任务来设计。编写程序就是编写执行特定任务的过程,过程中需要用到的数据通过过程参数传递到过程中。过程可以查看以及改变传递进来的数据,并可以将值返回给调用它的过程。

 

面向对象编程

OOP采用了一种完全不同的方法来开发计算机应用程序。在这种方法中,程序不是围绕着要解决的任务来设计,而是围绕着要解决的问题中的对象来设计。对于每个对象,我们会编写一个类来描述对象的属性和行为。类是对象的描述。同样,对象是类的实例。对象由属性和行为组成。属性是对象所具有的特征,而行为是对象可以做的动作。对象的每个属性被表示为类中的一个成员变量。对象的每个行为成为类中的一个方法。

 

结构化与面向对象的区别

面向过程(结构化):数据和处理数据的方法(函数)是分开的

面向对象(OOP):数据和处理数据的方法整合在一起

java结构化参数查询 java结构化编程的理解_java

 

Java中的类

  1. 类是具有相同属性和行为的一组对象的抽象
  2. 在软件系统中,我们用类来模拟现实生活中的实体

Java中的类用关键字class声明。Java源代码文件中只能包含一公用(public)类,文件名必须与公用类的类名相同,文件扩展名为“.java”。

注:在一个.java文件中我们可以声明多个类,但是只有一个类可以为声明为public。源代码文件的文件名必须与公用类的类名匹配。如果在源代码文件中没有公用类,文件名可以是任意的。例:

public class Employee {

}
class Employee2{
}


 

向类中添加成员变量

一个类的成员变量和方法出现在类声明的大括号中;java中成员变量就是属性,成员函数就是方法

对象的属性成为相关类中的成员变量。类中的一个成员变量由如下部分组成:

  • 访问修饰符。可以是public、private或protected;如果省略了访问修饰符,将使用默认访问修饰符。
  • 数据类型。
  • 成员变量名称。成员变量名称必须是一个有效的标识符,后面用分号结束。

例:

public class Employee {
    public String name;     //姓名
    public String address;     //邮寄地址
    public int number;     //员工号
    public int SSN;          //社保号
    public double salary;     //员工的工资
}

 

向类中添加方法

一个对象的行为成为相关类中的方法。类中的一个方法典型地由如下部分组成:

  • 访问修饰符
  • 返回值
  • 方法名称,必须是一个有效的标识符
  • 参数列表,在括号中出现
  • 方法的定义

例:

public class Employee {
    public String name;    //成员变量,也叫属性        
    public String address;   //成员变量,也叫属性  
    public int number;  //成员变量,也叫属性
    public int SSN;  //成员变量,也叫属性
    public double salary;  //成员变量,也叫属性

    //成员函数,也叫方法
    public void mailCheck() {
        System.out.println("邮寄支票到" + name  + ",地址为:\n" + address);
    }

    //成员函数,也叫方法
    public double computePay() {
        return salary/52;
    }
}

最后,我们可以看到Employee类中包含如下内容:

  • 类的名称是Employee。
  • 类有五个public成员变量。
  • 类有两个public方法。

 

实例化对象

在Java中,new关键字用于实例化一个对象。new运算符在内存中创建一个对象,并返回对新创建的对象的一个引用。只要我们的程序保留对该对象的一个引用,那么这个对象将一直保留在内存中。

下面的语句声明了一个Employee引用,并使用new关键字将该引用赋值给一个新的Employee对象:

Employee e;
e = new Employee();//实例化对象

引用e指向内存中的Employee对象。运算符new为该对象分配内存,然后将该对象的所有成员变量赋以初始值,这样,这些成员变量就不会包含垃圾数据。

表1 一个对象的成员变量的初始值

成员变量的数据类型

初始值

byte

0

short

0

int

0

long

0

float

0.0

double

0.0

char

空字符

boolean

false

任何类型的引用

null

实例化对象的两条语句可以合并为一条语句来实现。例如:

Employee e = new Employee();

例:

Employee e1, e2;
e1 = new Employee();
e2 = e1;    //有效

java结构化参数查询 java结构化编程的理解_对象_02

如图可看出:

  • e1,e2指向同一个对象,因为实例化在堆空间中的对象只new了一下。
  • 在e1中存放的是实例化 employee对象的地址
  • e2 = e1就是将e1中的地址赋值给e2,所以e1和e2指向了堆中同一片地址

 

访问对象的属性和方法

当我们使用new关键字实例化一个对象时,系统为会该类中的每个成员变量和方法分配内存。如果要访问该对象的成员变量和方法,就需要使用点运算符来。

例如,如下语句声明了一个Employee对象,然后修改该对象的name成员变量:

Employee e = new Employee();
e.name = "张三";

操作e.name是访问e引用的Employee对象的name成员变量的方法。同样,下面的语句使用点运算符调用这个特定Employee对象的mailCheck()方法:

e.mailCheck();

 

This引用

每个对象可以使用this关键字引用它本身。如果一个类的方法需要访问该类本身的成员变量或其它方法,就应该使用this引用。

This指针在你调用本身对象里的数据和方法的时候是默认使用this指针的,不管你写不写

如:

public double computePay() {
  return this.salary/52;
}

这里我们是自己添上后的代码,实际上你不写,在编译的时候编译器会给你自动添上

  • 我们可以将this应用作为参数给一个方法,通过这种方式,一个对象可以将它本身的引用传给其它对象。

例如:

上述代码的意思是将传进函数的参数salary赋值给本类中定义的salary

public class Pay{
    public int salary;
    public double computePay(int salary) {
        this.salary = salary;
        return this.salary;
    }
}

 

Java中的包

项目开发中,我们通常会编写数目众多的类。如果不对这些类进行分门别类的使用和存放,就像我们不使用文件夹去管理众多的文件一样,在使用时会很困难和不方便,也很容易出现类的命名冲突问题。Java通过引入包(package)的机制,以解决这两个问题。

在Java中,每个类属于一个包。包有两个基本的用途:

  • 提供了一个组织类的机制;
  • 为包中的类提供了一个命名空间。
  1. 在Java中,通过使用关键字package,可以将一个类声明在一个包中。
  2. 在Java中,包不仅仅是组织类的一种机制,更重要的一个特色是包所创建的命名空间。

在同一个文件夹和包下,我们不能声明文件名相同的文件,在我们使用包后,可以在不同包中声明和其他包中相同类名的类,来实现不同功能。


 

将类添加到包中

在创建类时,使用关键字package就可以将类添加到包中。包声明必须是源代码文件中除注释以外的第一条语句。

java结构化参数查询 java结构化编程的理解_包_03

 

包创建的命名空间

包为所有类创建了一个命名空间。如果类在一个包含中,那么包名就成为类名的一部分,包名作为类名的前缀,用点运算符分隔。

例如,Employee类在payroll包中声明。现在Employee类的全名为:

payroll.Employee

如果payroll包外的其它类想要使用Employee类,就必须在加上包名payroll。

包创建了命名空间,包名成为类名的前缀。命名空间的用途是为了避免两个同名类的命名冲突。


 

使用import关键字导入其它包中的类

如果一个类要使用同一包中的其它类,就不需要使用包名。同一个包中的类可以不需要特定的语法而相互找到。

但是,如果定义的Boss类不在定义的payroll包中会怎么样呢?在这种情况下,Boss类必须使用如下几种技术之一来引用位于不同包中的类:

  • 使用类的全名。例如,payroll.Employee。

java结构化参数查询 java结构化编程的理解_包_04

  • 使用关键字import以及通配符(*)导入包。例如,"import payroll.*;"。
  • 使用关键字import导入类本身。例如"import payroll.Employee;"。

java结构化参数查询 java结构化编程的理解_类_05

当使用另一个包中的类时,第三种用法是直接导入类本身。代码清单4.8中的Boss类中分别导入了另一个包中的类。

/* 代码清单4.8 Boss类
  演示import关键字的用法
*/

package management;
import payroll.Employee;

public class Boss{
    public void payEmployee(Employee e){
        e.mailCheck();
    }
}

 

分别导入每个类要键入更多字,但是这种用法比使用通配符的import语句更佳。在导入通配符时,某些特殊情况下会出现不能运行或者导致命名冲突。这种情况在本书所有代码中都不会出现,所以我们还是习惯性地使用通配符import语句。

分别导入类相对于导入整个包,没有任何大小或者性能上的好处。二者编译后的字节码是相同的,因为编译器会移除导入语句,并且用全限定名替换所有的类名。

迄今为止,我们已经在示例中始终使用了诸如String、System、Math和 Object等类。但是为什么我们没有用import关键字呢?这个因为这几个类都是在java.lang包中,而这个包是所有源代码文件中都要隐式导入的。

 

包目录结构

将类放在一个包中时,出现两个主要的结果:

  • 包名成为类名的一部分。
  • 包名必须与相关字节码存放的目录一致。

换句话说,包名会影响字节码存放的位置。例如,假如包com.lovoinfo.hr中存放了代表运输工具型号的类,其中有个名为Employee的类。那么,该类的全限定名就是com.lovoinfo.hr.Employee。

Java是对大小写敏感的。因为包名com.lovoinfo.hr都是小写,所以即使操作系统对大小写不敏感,目录名也必须是小写。

 

所需的文件结构可以用两种方式创建:

  • 我们可以手动创建目录,并将*.java文件保存在与*.class文件相同的目录中。然后,就可以按照常用的方式编译*.java文件,而编译产生的*.class文件都会放在*.java文件相同目录中。
  • 在编译时,使用javac编译器的-d标志,来指定字节码的输出目录。如果所需的包目录不存在,-d标记会创建目录,并将*.class文件放在恰当的文件夹。

这两种用法各有优点。第一种用法方便管理硬盘上的源代码;第二种用法在我们想把源代码和字节码分开的时候很方便,这在Java中部署应用程序时比较常见。

无论我们采用哪种方式,创建目录的过程都是很容易让人糊涂的,特别是当类不能相互找到时。

 

总结

  • 结构化编程围绕程序需要完成的任务来设计程序,而面向对象编程围绕问题域中的对象设计程序。
  • 面向对象分析和设计是判断问题域中的对象、决定这些对象之间的关系以及每个对象的属性和行为的过程。
  • 类是对象的描述,对象是类的实例。
  • 在Java中,关键字class用于声明一个类。类由成员变量和方法组成。
  • 关键字new用于实例化一个对象。new运算符返回对新创建的对象的一个引用。对象     在内存中,直到不再有任何引用指向它。此时,对象就符合垃圾回收的条件。
  • 点运算符用于与对象的一个引用一起访问对象的成员变量和方法。
  • 每个对象有一个对自身的引用,这个引用称为this引用。
  • 包是Java中组织和管理类的一种机制,同时可以防止类命名冲突。
  • 类中可以使用关键字import导入其他包中的类。

当我们要编译或者执行的类引用了其它的类,但是被引用类的.class文件不在当前目录下的时候,就需要设置环境变量CLASSPATH。