【1】java之类与对象
一、前言
面向对象就是一种组件化的设计思想。
面向对象特性
封装性:保护内部的定义结构安全性;
继承性:在已有的程序结构上继续扩充新的功能;
多态性:在某一个概念范围内的满足。
二、类与对象的定义和使用
2.1 定义类
使用 “ class 类名{}” 的语法结构完成:
- Field(属性 / 成员 / 变量)
- Method(方法 / 行为)
类的使用 —— 在主类中使用
2.2 定义对象
对象的定义有两种方法:
-
声明并实例化对象
类名称 对象名称 = new 类名称();
-
分步完成
类名称 对象名称 = null;
对象名称 = new 类名称();
引用数据类型与基本数据类型最大的不同在于需要内存空间的开辟及使用,所以关键字 new 的作用就是开辟内存空间,即只要使用引用类型,必须使用关键字 new 来开辟内存空间。
2.3 内存空间
两块内存空间的概念:
- 堆内存:保存每一个对象的属性内容,需要使用关键字 new 才可以开辟,所有的堆内存空间是有地址的;
- 栈内存:保存的是一块堆内存的地址。为了分析方便,可以简单的理解栈内存保存的是对象名字。
任何情况下只要看见了关键字 new,都表示要开辟新的堆内存空间,一旦堆内存空间开辟了,里面就一定会有类中定义的所有的属性,属性的值为其对应数据类型的默认值。
开辟了堆内存的对象称为实例化对象。那么如果使用了没有实例化的对象,如下所示:
Book bk = null;
bk.title = "Java 开发";
由于使用了没有实例化对象,所以在程序运行时出现了 “NullPointerException” ,此类异常只要是引用数据类型都可能会出现。
三、类与对象(对象引用分析)
3.1 引用数据的初步分析
在所有的引用分析里,最关键的是关键字 new,一定要注意的是,每一次 new 都是生成新的堆内存空间,所以如果你的代码里声明了两个对象,并且使用了关键字 new 为每个对象开辟了堆内存空间,那么一定是各自占有各自的堆内存空间,并且不会互相影响。
举例:声明两个对象
Book bookA = new Book();
Book bookB = new Book();
bookA.title = "Java 开发";
bookA.price = "89.8";
bookB.title = "JSP 开发";
bookB.price = "69.8";
引用类型的使用 —— 引用类型的传递举例
Book bookA = new Book();
bookA.title = "Java 开发";
bookA.price = "89.8";
Book bookB = bookA; // 这里就是引用传递。
bookB.price = "69.8";
bookA 和 bookB 指向的是同一块堆内存,所以任何一个对象修改了堆内存中的数据后,都会影响其他对象。在引用的操作过程中,一块堆内存可以同时被多个栈内存所指向,但是反过来,一块栈内存只能保存一块堆内存空间的地址。
3.2 垃圾
继续观察引用传递
Book bookA = new Book();
Book bookB = new Book();
bookA.title = "Java 开发";
bookA.price = "89.8";
bookB.title = "JSP 开发";
bookB.price = "69.8";
Book bookB = bookA; // 这里就是引用传递。
bookB.price = "100.1";
通过内存的分析可以发现,在引用数据类型关系里面,一块没有任何栈内存指向的堆内存空间就将成为垃圾,所有的垃圾会不定期的被垃圾回收机(GC)进行回收,回收之后会释放掉其所占用的空间。
虽然在 Java 里面支持了自动的垃圾收集处理,但是在代码的开发过程中应该尽量的减少垃圾空间的产生。
3.3 一段总结
1、声明对象指的是未开辟堆内存的对象,如果直接使用此对象会出现“NullPointerException”;
2、对象可以通过关键字 new 来进行堆内存空间的开辟,有了堆内存引用的对象才称为实例化对象;
3、堆内存保存的是对象所有属性的内容,而栈内存保存的是堆内存的地址数值(为简单理解才称栈内存保存的是对象名称);
4、垃圾空间指的未被任何栈内存指向的堆内存空间,会被 GC 不定期进行回收
四、封装性
4.1 封装的实现
所有在类中定义的属性都要使用 private 声明,这样属性只能在本类可以访问;如果属性要被外部的类访问,则要定义相应的 setter、getter 方法。
五、构造方法与匿名对象
5.1 构造方法的作用
Book book = new Book();
构造方法的核心作用:在类对象实例化的时候设置属性的内容。
在定义一个类的时候,可以为属性设置默认值,但是这个默认值只有在构造方法执行完成后才会设置。
class Book{
private String title = "Java 开发";
public Book(){}
}
本程序之中,只有在整个构造都完成之后,才会真正将 “Java 开发” 这个字符串的内容赋值给 title,在构造方法执行执行之前,title 都是其对应数据类型的默认值。
5.2 匿名对象的基本使用
没有栈指向的对象就称为匿名对象。
new Book("Java 开发",89.8).getInfo();
但是匿名对象由于没有其他对象对其进行引用,所以只能使用一次,一次使用之后该对象就会成为垃圾,等待被回收。
5.3 一段总结
构造方法的定义要求:方法名称与类名称相同,无返回值声明;
构造方法是在类对象使用关键字 new 实例化的时候被默认调用的,不管代码如何改变,只要有 new 就一定需要构造方法;
一个类中至少会保留一个构造方法,如果没有明确定义,会自动的生成一个无参的什么都不做的默认构造方法;
构造方法的核心功能:在类对象实例化的时候为类中的属性初始化;
构造方法重载时只要求考虑参数类型和个数即可;
匿名对象只能使用1次。
六、示例
开发一个雇员的类。包含有雇员编号、姓名、职位、基本工资。
这种功能的类在开发之中称为简单 Java 类,因为这些类里面不会包含有过于复杂的程序逻辑。
对于简单 Java 类而言,现在给出它的第一种开发要求:
-
类名称必须存在有意义,例如:Book、Employee;
-
类之中所有的属性必须用 private 封装,封装后的属性必须提供 setter、getter;
-
类之中可以提供任意多个构造方法,但是 必须保留有一个无参构造方法;
-
类之中不允许出现任何的输出语句,所有信息的输出必须交给被调用输出;
-
类之中需要提供一个取得对象完整信息的方法,暂定为:getInfo,而且返回为String类型数据。
class Employee{ private int empId; private String name; private String job; private double salary; public Employee(){} public Employee(int id, String name, String job,double salary){ this.empId = id; this.name = name; this.job = job; this.salary = salary; } public void setEmpNo(int id){ this.empId = id; } public void setName(String name){ this.name = name; } public void setJob(String job){ this.job = job; } public void setSalary(double salary){ this.salary = salary; } public int getEmpId(){return this.empId;} public String getName(){return this.name;} public String getJob(){return this.job;} public double getSalary(){return this.salary;} public String getInfo(){ return "雇员编号: " + this.empId + "\\n" + "姓 名: " + this.name + "\\n" + "职 位: " + this.job + "\\n" + "薪 资: " + this.salary + "\\n"; } }
-
编写测试程序
public class EmployeeTest{ public static void main(String[] args){ Employee emp = new Employee(456, "jinhua.chen", "test-devloper", 1000.0); emp.setJob("QA"); System.out.println(emp.getInfo()); } }
类中提供的所有 setter、getter 方法可能某些操作不会使用到,但是依然必须提供。所有的 setter 方法除了具备有设置属性的内容之外,也能修改属性的内容。