Skip to main content

面向对象特征

面向过程和面向对象

面向过程

以具体的求解过程为研究和实现的主体,过程完备。如C语言。
缺点:无法将复杂的系统描述清楚,很难满足现在对软件规模和复杂度的需求。

面向对象

以求解问题中所涉及的各种对象为主体,力图求解过程符合人们日常的思维习惯,降低了求解问题的难度和复杂性,提高了编程的效率,比如C++,Java语言。

面向对象的基本特征

封装
将数据(属性)和对数据的操作(功能)封装在一起。成员变量,成员方法,类.
继承
子类可以继承父类的属性和功能,同时又可以增加子类独有的属性和功能。
多态
多个操作具有相同的名字,但是接受的消息类型必须不同。
同一个操作被不同类型的对象调用时产生不同的行为。

类和对象

类的基本结构

class 机动车    // 类声明
{
// 成员变量
int speed;
float height;
float weight;
// 成员方法
void changSpeed(int newSpeed)
{ speed=newSpeed; }
float getWeight()
{ return weight; }
float getHeight()
{ return height; }
}

构造方法

  • 类创建对象时,需要使用构造方法完成对象的初始化工作。
  • 构造方法的名称必须与类名相同。
  • 构造方法没有返回值
  • 一个类中可以有若干个构造方法(名称相同),但是构造方法的参数必须不同。
  • 如果类中没有构造方法,系统为类定义一个默认的构造方法,该构造方法没有参数,类体为空。
class Rect
{
double sideA,sideB;
Rect( ){ } //无参构造方法
Rect(double a, double b){ //有参构造方法,初始化对象的两个属性
sideA=a;
sideB=b;
}
double computeArea( ){
return sideA*sideB;
}
double computeGirth( ){
return (sideA+sideB)*2;
}
}

对象的创建和使用

对象声明

类的名字 对象名字

Rect rectangleOne;
rectangleOne 是一个空对象,它不能访问成员变量和成员方法

对象的创建

对象名=new 构造方法名(参数列表)

rectangleOne=new Rect( );
rectangleOne=new Rect(10, 20);
rectangleTwo=new Rect(33, 66);

//也可以把声明对象和创建对象合在一起进行
Rect rectangleOne=new Rect(10,20);

对象的使用

对象名.成员变量名
对象名.成员方法名(参数列表)

rectangleOne.sideA=10;
rectangleOne.sideB=20;
rectangleOne.computeArea( );
rectangleOne.computeGirth( );

成员变量

实例变量

不用关键字 static 修饰。
一个类中不同对象的实例变量将被分配不同的存储空间。
只能通过对象访问实例变量。

静态变量(类变量)

用关键字 static 修饰。
一个类中所有对象的某个静态变量被分配同一个内存,所有对象共享这个静态变量
可以通过类名访问静态变量,也可以通过某个对象访问静态变量。

class Circle
{
static double pi; //类变量
double radius; //实例变量
}
Circle.pi=3.14;
Circle circle1=new Circle();
circle1.radius=10;
Circle circle2=new Circle();
circle2.radius=100;

1

在上面的代码中, Pi 作为公共的区域,所有对象共享一个内存。

常量

final 成员变量
如果一个成员变量修饰为final,就是常量。常量的名字习惯用大写字母。

final int MAX=100;
tip

如果final变量是简单类型,则其值不能发生变化
如果final变量是复合类型,则其指向对象的引用不能发生变化

类的封装

封装:将类的属性和方法封装在一个类中,对外提供一个统一的接口,隐藏类的内部实现细节。在定义一个类时,我们可以把它的属性私有化,使用 private 修饰。让这个属性只能在类中被访问,当外部需要访问或设置这个属性时,我们可以提供一个公共的方法来访问这个属性。

class Person
{
private String name; //私有属性
public String getName( ){ //公共方法
return name;
}
public void setName(String name){ //公共方法
this.name=name;
}
}

利用这个方法,我们可以对外部传入的参数进行验证,保证数据的准确性和安全性。比如下面的例子中,我们对外部传入的年龄进行了验证,如果年龄小于0或者大于150,就抛出一个异常。

class Person
{
private int age;
public int getAge( ){
return age;
}
public void setAge(int age){
if(age<0 || age>150){
throw new RuntimeException("年龄不合法");
}
this.age=age;
}
}

构造方法

构造方法是一个特殊的方法,它在对象创建时被调用。如果一个类中没有定义构造方法,那么编译器会自动为这个类添加一个无参的构造方法。如果需要在对象创建时对对象属性进行初始化,就需要定义构造方法。

class Person
{
private String name;
private int age;
public Person(String name,int age){ //有参构造方法
this.name=name;
this.age=age;
}
}

还有一种构造方法,就是无参构造方法

class Person
{
private String name;
private int age;
public Person( ){ //无参构造方法
this.name="张三";
this.age=20;
}
}

构造方法是可以被重载的,也就是说,一个类中可以有多个构造方法。

class Person
{
private String name;
private int age;
public Person( ){ //无参构造方法
this.name="张三";
this.age=20;
}
public Person(String name,int age){ //有参构造方法
this.name=name;
this.age=age;
}
}

在上面的代码中,当我们创建一个对象时,可以使用无参构造方法,也可以使用有参构造方法。使用无参构造方法时,对象的属性会被初始化为默认值。

Person p1=new Person( ); //使用无参构造方法
Person p2=new Person("李四",30); //使用有参构造方法

this 关键字

Java 中的 this 关键字是一个引用,它指向当前对象。

class Person
{
private String name;
private int age;
public Person( ){
this.name="张三";
this.age=20;
}
public Person(String name,int age){
this.name=name;
this.age=age;
}
public void print( ){
// this.name 等价于 name
System.out.println("姓名:"+this.name+",年龄:"+this.age);
}
}

this 关键字也可以用来调用当前类中的其他方法。

class Person
{
private String name;
private int age;
public Person( ){
this.name="张三";
this.age=20;
}
public Person(String name,int age){
this.name=name;
this.age=age;
}
public void print( ){
System.out.println("姓名:"+this.name+",年龄:"+this.age);
}
public void printInfo( ){
this.print( );
}
}

构造方法之间可以通过 this 关键字来调用。

class Person
{
private String name;
private int age;
public Person( ){
this.name="张三";
this.age=20;
}
public Person(String name,int age){
this.name=name;
this.age=age;
}
public Person(String name){
// 调用两个参数的构造方法
this(name,20);
}
public void print( ){
System.out.println("姓名:"+this.name+",年龄:"+this.age);
}
}

垃圾回收

Java 中的垃圾回收是自动的,不需要程序员手动去释放内存。但是我们也可以通过 System.gc( ) 方法来强制垃圾回收。

class Person
{
private String name;
private int age;
public Person( ){
this.name="张三";
this.age=20;
}
public Person(String name,int age){
this.name=name;
this.age=age;
}
public void print( ){
System.out.println("姓名:"+this.name+",年龄:"+this.age);
}
public void finalize( ){
System.out.println("对象被回收了");
}
}

在上面的代码中,我们重写了 finalize( ) 方法,当对象被回收时,会调用该方法。

Person p=new Person( );
p=null;
System.gc( );

static 关键字

静态变量

当多个对象共享同一个属性时,可以将该属性定义为静态变量。

class Person
{
// 静态变量
private static String country="中国";
private String name;
private int age;
public Person( ){
this.name="张三";
this.age=20;
}
public Person(String name,int age){
this.name=name;
this.age=age;
}
public void print( ){
System.out.println("姓名:"+this.name+",年龄:"+this.age+",国家:"+country);
}
}

为静态变量赋值时,可以通过类名来访问。

Person.country="美国";

static只能修饰成员变量,不能修饰局部变量。它是非法的。

class Person
{
public void print( ){
// 非法的
static int a=10;
}
}

静态方法

当多个对象共享同一个方法时,可以将该方法定义为静态方法。

class Person
{
private String name;
private int age;
public Person( ){
this.name="张三";
this.age=20;
}
public Person(String name,int age){
this.name=name;
this.age=age;
}
public void print( ){
System.out.println("姓名:"+this.name+",年龄:"+this.age);
}
// 静态方法
public static void printInfo( ){
System.out.println("这是一个静态方法");
}
}

静态代码块

静态代码块是在类加载时执行的,只执行一次。

class Person
{
// 静态代码块
static{
System.out.println("这是一个静态代码块");
}
//...
}

在主函数调用时,静态代码块会先执行。

public class Main
{
public static void main(String[] args)
{
// 静态代码块会先执行
// 声明 Person 对象
Person p=new Person( );
}
}

内部成员类

内部成员类是定义在类中的类,它可以访问外部类的所有成员,包括私有成员。

class Person
{
private String name;
private int age;
public Person( ){
this.name="张三";
this.age=20;
}
public Person(String name,int age){
this.name=name;
this.age=age;
}
public void print( ){
System.out.println("姓名:"+this.name+",年龄:"+this.age);
}
// 内部成员类
class PersonInfo
{
public void print( ){
System.out.println("姓名:"+Person.this.name+",年龄:"+Person.this.age);
}
}
}

如果希望调用内部成员类的方法,可以通过外部类的对象来调用。

Person p=new Person( );
Person.PersonInfo pi=p.new PersonInfo( );
pi.print( );