(局部变量需要初始化,全局变量不初始化系统也会帮忙初始化而局部变量系统不会帮忙初始化)
>>>
2.1 类与对象基本概念
在现实生活之中,类指的就是具备某一共性的群体集合。而对象是一种个性的描述。如果要想进行更简单的理解。对象包含的是具体的信息内容,例如:曾公子,李老师,JAVA开发。我需要招聘一个秘书,而秘书是一个标准
对象所能够具备的操作行为实际上是由类来定义的,也就是说要想使用类那么必须有一个具体的描述对象,而对象的操作完全由类来定义。对象是可以明确使用的,而类是不能够直接使用的。
真实存在的可以使用的就是对象,而定义概念的就是类。类是对象的操作标准,而对象是类的操作实例,类中没有定义的操作,对象一定不能够使用
2.2·类与对象的定义(重点)
在开发之中一定要记住,先有类,再有对象。在JAVA中如果要定义类,则可以使用 class 关键字来描述,而在类中的组成主要有两种:属性(变量),方法(此方法不是在主类中定义,不由主方法直接调用,所以不加 static)。
范例:定义一个类
class Person{ // 现在定义了一个类 // 定义类中的两个属性 String name; // 表示人的姓名 int age; // 表示人的年纪 public void tell(){ System.out.println('姓名:' + name + ',年纪:' + age); } } public class TestDemo{ public static void main(Srting args[]){ } }
类本身不能够直接使用,所有的类必须通过对象才可以使用。由于类属于引用数据类型(内存关系),所以对象的定义语法现在有两种:
声明并实例化对象:类名称 对象名称 = 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(Srting args[]){ Person per = new Person(); // 声明并实例化对象 per.name = '张三'; // 对象.属性= 内容 per.age = 30; // per.tell(); // 通过对象调用类中的方法 } } // 返回姓名:张三,年纪:30
整个的代码操作就是根据一个类产生处对象,而后设置对象的属性内容,并且打印信息。
如果此时没有设置属性内容呢?
class Person{ // 现在定义了一个类 // 定义类中的两个属性 String name; // 表示人的姓名 int age; // 表示人的年纪 public void tell(){ System.out.println('姓名:' + name + ',年纪:' + age); } } public class TestDemo{ // 另一个类 public static void main(Srting args[]){ Person per = new Person(); // 声明并实例化对象 // per.name = '张三'; // 对象.属性= 内容 // per.age = 30; // per.tell(); // 通过对象调用类中的方法 } } // 返回姓名:null,年纪:0
没有设置属性内容时出现的就是默认值,String 是引用类型,所以默认值是 null,而 int 是基本数据类型,默认值为0.
2.3对象产生或引用的初步分析
类本身属于引用数据类型,所以对于引用数据类型就必须为其进行内存分析,分析之前,首先给出两块内存空间的定义:
堆内存空间(Heap):保存的是对象中具体属性信息(真正的对象)
栈内存空间(Stack):是保存 堆内存的地址数值,所以现在可以简化一点,假设保存在栈内存中的是对象名称。一个栈内存只能够保存一块对应的堆内存空间地址。
所以现在按照以上的分析,就可以的出如下内存关系图。
范例:分析代码(有个 new 就是开辟空间 )
引用数据使用与C语言是完全一样的,所以这个是JAVA的灵魂存在。
实际上对象的产生格式本次只使用了一种,还有另外一种分步的方式完成。
class Person{ // 现在定义了一个类 // 定义类中的两个属性 String name; // 表示人的姓名 int age; // 表示人的年纪 public void tell(){ System.out.println('姓名:' + name + ',年纪:' + age); } } public class TestDemo{ // 另一个类 public static void main(Srting args[]){ Person per = null; // 声明对象 per = new Person(); //实例化对象 per.name = '张三'; // 对象.属性= 内容 per.age = 30; per.tell(); // 通过对象调用类中的方法 } }
注意:关于引用数据类型操作存在的重要问题。
理论上当对象开辟堆内存(实例化对象)那么属性才会进行内存的分配,那么如果说使用了没有实例化的对象呢?
class Person{ // 现在定义了一个类 // 定义类中的两个属性 String name; // 表示人的姓名 int age; // 表示人的年纪 public void tell(){ System.out.println('姓名:' + name + ',年纪:' + age); } } public class TestDemo{ // 另一个类 public static void main(Srting args[]){ Person per = null; // 声明对象 // per = new Person(); //实例化对象 per.name = '张三'; // 对象.属性= 内容 per.age = 30; per.tell(); // 通过对象调用类中的方法 } }
相当于此时只是声明了对象,但是并没有进行对象的实例化操作,这个时候程序编译没有任何问题,但是程序执行。
那么此时返回的是“NullPointerException”异常,翻译就是空指向异常,这个异常只有引用数据类型会出现,出现的原因只有一点:使用了没有开辟堆内存空间的引用对象。
现在既然已经可以开辟一个对象了,那么也就可以开辟两个对象。
范例:开辟两个对象操作
class Person{ // 现在定义了一个类 // 定义类中的两个属性 String name; // 表示人的姓名 int age; // 表示人的年纪 public void tell(){ System.out.println('姓名:' + name + ',年纪:' + age); } } public class TestDemo{ // 另一个类 public static void main(Srting args[]){ Person perA = new Person(); // 声明并实例化对象 Person perB = new Person(); perA.name = '张三'; // 对象.属性= 内容 perA.age = 30; perB.name = '王五'; perB.age = 10; perA.tell(); // 通过对象调用类中的方法 perB.tell(); } } /* 返回 姓名:张三,年纪:30 姓名:王五,年纪:10 */
2.4·初步分析引用传递
引用传递是在引用数据类型上所用的一个操作定义,其是JAVA的 精髓,其操作的性质与C语言的指针是相同的,进行内存的操作。换到程序中,那么就是一块堆内存空间可以同时被多个栈内存所指向。
范例:
把perA保存的堆内存地址给了perB
以上是采用了声明对象的方式进行引用数据类型的接收,那么如果说此时两个对象都已经明确实例化并设置内容了呢?
范例:观察引用类型
class Person{ // 现在定义了一个类 // 定义类中的两个属性 String name; // 表示人的姓名 int age; // 表示人的年纪 public void tell(){ System.out.println('姓名:' + name + ',年纪:' + age); } } public class TestDemo{ // 另一个类 public static void main(Srting 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(); // 通过对象调用类中的方法 } }
通过以上的分析应该可以发现几点:
使用关键字 new 永恒可以开辟新的堆内存空间,堆内存空间保存的就属性
栈内存只能够保存一块堆内存的使用地址
引用传递的本质在于同一块堆内存空间可以被不同的栈内存所指向
在发生引用传递时,如果操作的栈内存原本有堆内存指向,那么改变堆空间就意味着改变内存指向
如果某一块堆内存没有被任何的栈内存所指向,那么此空间将成为垃圾空间,所有的垃圾空间会自动的被 GC (垃圾收集器,Garbage Collector)回收并释放。由于垃圾回收是不确定的执行时间,所以最好的作法是尽量少产生垃圾空间。
如果要想产生垃圾,除了改变引用之外,也可以设置我为 null( perB = null 那么表示 perB 将放弃原本的指向,变为一个没有指向的栈内存)
>>>>
清楚类与对象的定义格式
熟练掌握对象的内存分配,以及内存图的描述