【面向对象】类与对象

# 面向对象简介

Java语言最大的特点在于面向对象的编程设计,并且面向对象的编程设计也在由于Java自身的发展而不断发展,最初不支持面向对象的编程也开始转向了面向对象,但是依然有许多的开发者认为面向过程比较好,或者使用函数式编程会比较好。

最早并且一直到现在流行的编程语言 C、C++、Java。其中 C 语言已经变成了面向过程开发的代表,而像 C++、Java是面向对象的编程语言。

所谓的面向过程指的是面对一个问题的解决方案。更多的情况下是不会做出重用的设计思考,而面向对象的设计形式为模块化设计, 并且可以进行重用配置。在整个面向对象的设计里面,更多情况下考虑的是标准,在使用的时候根据标准进行拼装。

对于面向对象有三个主要特征:

  • 封装性:内部的操作对于外部不可见,当内部操作全部不可见的时候才是安全的;
  • 继承性:在已有结构的基础上继续进行功能的扩充;
  • 多态性:是在继承性的基础上扩充来的概念,指的是类型的转换处理。

在进行面向对象重新开发之中一般还有三个步骤:

  • OOA:面向对象分析;
  • OOD:面向对象设计;
  • OOP:面向对象编程。

# 类与对象简介

面向对象是一个非常庞大的话题,但是任何庞大的话题都有其核心的组成:类与对象。

​ 类是对某一类事物共性的抽象概念,而对象描述的是一个具体的产物。

例如:现在我和某一位先生进行比较的时候,你们可以立刻区分出我和别人。

我和其他人都一样,都是一个个具体可以使用的个体产物。但是这些个体都有一些共性标志:中国人,但是这些人和人是不同的。所谓的人和人之间的不同,依靠的是我们各自的属性。每一个属性的集合就构成了一个对象,但是所有的属性都应该是群体的定义,而群体的定义就形成了一个类。

img

类是一个模板,而对象才是类可以使用的实例。先有类,再有对象。

在类之中一般都会有两个组成:

  • 成员属性(Field):有些时候为了简化称其为属性;

    • 一个人的年龄、姓名都是不同的,所以这些对于整体来讲就称为属性;
  • 操作方法(Method):定义对象具有的处理行为;

    • 这人可以唱、跳、rap、篮球;

# 类与对象的定义和使用

在Java中,类是一个独立的结构体,所以需要使用 class 来进行定义,而在类之中主要由属性和方法所组成,属性就是一个个具体的变量,方法就是可以重复执行的代码。

范例:定义一个类

class Person{
    String name;	// 人员的姓名
    int age;		// 人的年龄
    public void tell(){
        System.out.println("姓名" + name + "、年龄:" + age);
    }
}

在这个类中,定义有两个属性(name, age)和一个方法( tell() ),现在有了类之后,如果想用使用类,那么就必须通过对象来完成,而如果要产生对象,那么就必须使用如下的语法格式来完成:

  • 声明并实例化对象:类名称 对象名称 = new 类名称();

  • 分步骤完成:

    • 声明对象:类名称 对象名称 = null;
    • 实例化对象:对象名称 = new 类名称()

当获取了实例化对象之后,那么就需要通过对象进行类中的操作调用,此时有两种调用方式:

  • 调用类中的属性:实例化对象.成员属性;
  • 调用类中的方法:实例化对象.方法名称()

范例:使用对象操作类

class Person{
    String name;	// 人员的姓名
    int age;		// 人的年龄
    public void tell(){
        System.out.println("姓名" + name + "、年龄:" + age);
    }
}
public class JavaDemo{
    public static void main(String args[]){
        Person per = new Person(); //  声明并实例化对象
        per.name = "张三";
        per.age = 18;
        per.tell(); // 方法的调用	
    }
}

如果此时的出现你并没有进行对对象属性内容的设置,则该数据内容为其对应数据类型的默认值。

class Person{
    String name;	// 人员的姓名
    int age;		// 人的年龄
    public void tell(){
        System.out.println("姓名" + name + "、年龄:" + age);
    }
}
public class JavaDemo{
    public static void main(String args[]){
        Person per = new Person(); //  声明并实例化对象
        per.tell(); // 方法的调用	
    }
}
// 打印结果
姓名:null、年龄:0

String 是引用数据类型 所以默认值为 null,而 int 为基本类型,默认值为 0

# 对象内存分析

对象实例化操作初步分析

Java 之中类属于引用数据类型,引用数据类型最大的困难之处在于要进行内存的管理,同时进行操作的时候也会发生有内存关系的变化。

所以本次针对于之前的出现的内存关系进行一些简单分析。

范例:以下面的程序为主进行分析。

public class JavaDemo{
    public static void main(String args[]){
        Person per = new Person(); //  声明并实例化对象
        per.name = "张三";
        per.age = 18;
        per.tell(); // 方法的调用	
    }
}

如果要进行内存分析,那么首先给出两块最为常用的内存空间:

  • 堆内存:保存的是对象的具体信息,在程序之中,堆内存空间的开辟是通过 new 完成的。
  • 栈内存:保存的是一块堆内存的地址,即:通过地址找到堆内存,而后找到对象内容,但是为了分析简化起见,可以简单的将他理解为:对象的每次保存在了栈内存之中。

img

清楚了以上的对应关系之后,那么下面就针对于之前的程序进行分析:

img

在之前进行分析的时候可以发现对象的实例化有两种语法,一种是之前使用的声明并实例化对象,另外一种就是分布完成,所以下面对于分布的内存操作进行分析:

范例:定义程序代码

public class JavaDemo{
    public static void main(String args[]){
        Person per = null; // 声明对象
        per = new Person(); // 实例化对象
        per.name = "张三";
        per.age = 19;
        per.tell(); // 进行丰富的调用
    }
}

下面通过内存分析来进行操作:

img

需要特别引起注意的是,所有的对象在调用类中的属性或者方法的时候必须要实例化完成之后才可以执行。

范例:错误的代码

public class JavaDemo{
    public static void main(String args[]){
        Person per = null; // 声明对象
        per.name = "张三";
        per.age = 19;
        per.tell(); // 进行丰富的调用
    }
}

代码之中只是声明了对象,但是并没有为对象进行实例化,所以此时无法调用。而此时程序中出现的 NullPointerException (空指向异常)就是在没有在堆内存开辟后所产生的问题,并且只有引用数据类型存在有此问题。

Exception in thread "main"java.lang.NullPointerException
            at JavaDemo.main(JavaDemo.java:11).
// 没有实例化对象 - 空指向异常

# 对象引用分析

引用传递分析

类本身属于引用数据类型,既然是引用数据类型,那么就牵扯到内存的引用传递,所谓的引用传递本质:同一块堆内存空间可以被不同的栈内存所指向,也可以更换指向。

范例:定义一个引用传递的分析程序

public class JavaDemo{
    public static void main(String args[]){
        Person per1 = new Person();
        per1.name = "张三";
        per1.age = 18;
        Person per2 = per1; //引用传递
        per2.age = 80;
        per1.tell();
    }
}

img

这个时候的引用传递是直接在主方法之中定义的,也可以通过方法实现引用传递处理。

范例:利用方法实现引用传递处理

public class JavaDemo{
    public static void main(String args[]){
        Person per = new Person(); // 声明并且实例化对象
        per.name = "张三";
        per.age = 18;
        change(per); // 等价于 Person tmp = per;
        per.tell(); // 进行方法的调用
    }
    public static void change(Person tmp){
        tmp.age = 80;
    }
}

​ 与之前的差别最大的地方在于,此时的程序是将 Person 类的实例化对象(内存地址、数值)传递到了change() 方法之中,由于传递的是一个 Person 类型,那么 change() 方法接收的也是 Person 类型。

img

引用传递可以发生在方法上,这个时候一定要观察方法的参数类型,同时也要观察方法的执行过程。

# 引用传递与垃圾产生分析

经过了一系列的分析之后已经确认,所有的引用传递的本质就是一场堆内存的调戏游戏。但是对于引用传递处理不当,那么也会造成垃圾的产生。那么本次我们将针对于垃圾产生的原因进行分析。

范例:定义一个要分析的程序

public class JavaDemo{
    public static void main(String args[]){
        Person per1 = new Person();
        Person per2 = new Person();
        per1.name = "张三";
        per1.age = 18;
        per2.name = "李四";
        per2.age = 19;
        per2 = per1;
        per2.age = 80;
        per1.tell();
    }
}
// 张三 80

​ 此时已经明确发生了引用传递,并且也成功的完成了引用传递的处理操作,但是下面来观察一下其内存的分配与处理流程。

一个栈内存只能够保存有一个堆内存的地址数据,如果发生更改,则之前的地址数据将从此栈内存中彻底消失。

img

所谓的垃圾空间指的就是没有任何栈内存所指向的堆内存空间,所有的垃圾将被 GC(Garbage Collector、垃圾收集器)不定期进行回收并且释放无用内存空间,但是如果垃圾过多,一定将影响到 GC 的处理性能,从而降低整体的程序性能,那么在实际的开发之中,对于垃圾的产生应该越少越好。

  • 16
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值