面向过程指的是只完成自己所需要的操作,但是这种设计缺少可维护性。e.g. 造一辆车,零件全是自己造的。;
面向对象指的是一种组件化(模块化)设计。方便进行代码的局部维护。但是设计上的要求规范比较多。也就是说模块化的设计最重要的是标准,以及项目的整体的把控。
面向对象里面分为以下几个特点:
封装性:保护内部的操作对外部不可见;
继承性:相当于一代代传承;
多态性:在一个范围内的定义的改变;
类的组成:属性(变量)、方法(此方法不是在主类中定义,不由主方法直接调用,不加static);
范例:定义一个类
Class Person{
String name;
int age; //定义两个属性(变量)
public void tell() {
System.out.println(name + " , " + age );
}
}
类本身不能直接使用,所有的类必须通过对象才能使用;由于类属于引用数据类型(有内存关系),所以对象的定义语法有两种:
声明并实例化对象:类名称 对象名称 = new 类名称();
分步进行:
声明对象:类名称 对象名称 = null;
实例化对象:对象名称 = new 类名称();
引用数据类型在使用之前必须开辟空间,而基本数据类型可以直接赋值,开辟新的内存空间的关键字为new;
一旦有了对象后,就可以用对象来实现类中属性和方法:
调用属性:实例化对象.属性名称;
调用方法:实例化对象. 方法();
范例:定义对象并使用:
Class Person{
String name;
int age; //定义两个属性(变量)
public void tell() {
System.out.println(name + " , " + age );
}
}
public class TestDemo{
public static void main(String args[]){
Person per = new Person(); //声明并实例化对象
per.name = "张三" ;
per.age = 30;
per.tell();
}
}
类属于引用数据类型,因此必须为其进行内存分析。
两个内存空间概念:
堆内存空间(Heap):保存的是对象中具体的属性信息;
栈内存空间(Stack):保存的堆内存的地址数值,假设保存在栈内存的是对象名称。按照以上分析得出以下内存关系图:
引用数据使用与C语言一样。
分步声明和实例化对象内存分析:
Class Person{
String name;
int age; //定义两个属性(变量)
public void tell() {
System.out.println(name + " , " + age );
}
}
public class TestDemo{
public static void main(String args[]){
Person per = null; //声明对象
per = new Person(); //实例化对象
per.name = "张三" ;
per.age = 30;
per.tell();
}
}
注意:关于引用数据类型操作存在的重要问题:
理论上当对象开辟堆内存(实例化对象)那么属性才会进行内存分配,那么如果使用了没有实例化的对象呢?这个时候程序编译没问题。
此时返回的是“NullPointerException”异常,翻译:空指向异常,这个异常只有引用数据类型会出现,原因只有一点:使用了没有开辟内存空间的引用对象。
初步分析引用传递
引用传递是在引用数据类型上所用的一个操作定义,是Java精髓,操作与C的指针相同。针对内存进行操作。
换到程序中就是一块堆内存空间可以同时被多个栈内存所指向。
范例:引用传递
Class Person{
String name;
int age; //定义两个属性(变量)
public void tell() {
System.out.println(name + " , " + age );
}
}
public class TestDemo{
public static void main(String args[]){
Person perA = new Person();
perA.name = "张三" ;
perA.age = 30;
Person perB = perA; //引用传递
perB.name = "李四" ;
perA.tell();
}
}
结果:李四 30
以上是采用了声明对象的方式进行了引用数据类型的接收,那如果两个对象都已经明确实例化并设置内容了呢?
范例:
Class Person{
String name;
int age; //定义两个属性(变量)
public void tell() {
System.out.println(name + " , " + age );
}
}
public class TestDemo{
public static void main(String args[]){
Person perA = new Person();
Person perB = new Person();
perA.name = "张三" ;
perA.age = 30;
perB.name = "王五" ;
perB.age = 10;
perB = perA; //引用传递
perB.name = "赵六 ;
perA.tell();
}
}
结果:赵六 30
通过以上的分析,应该可以发现:
使用关键字new永恒可以开辟新内存空间,堆内存保存的就是属性
栈内存只能够保存一块堆内存的使用地址
引用传递的本质在于同一块堆内存空间可被不同的栈内存所指向
发生引用传递时,如果操作的栈内存原本有堆内存指向,那么改变对空间就意味着改变内存指向
如果某一块堆内存没有任何栈内存所指向,那么此空间将成为垃圾空间,所有的垃圾空间会自动的GC(垃圾收集器 Garbage Collector)回收并且释放,由于垃圾回收时间不确定所以少产生垃圾空间。
如果想产生垃圾,除了改变引用之外,也可以设置为空null。perB = null;那就表示放弃原本的指向,变为一个没有指向的栈内存。