JavaSE基础第七章(对象的创建与使用)

JavaSE基础第七章(对象的创建与使用),第1张

JavaSE基础第七章(对象的创建与使用)

文章目录
  • 一、对象的创建和使用
    • 1、对象的创建
    • 2、对象的使用
  • 二、对象创建和使用的深层次解密
    • 1.java 虚拟机内存管理
    • 2.构造方法Constructor
    • 3.空指针异常
    • 4.方法调用时参数的传递问题
  • 总结

一、对象的创建和使用 1、对象的创建

类定义之后,就可以使用类这个“模板”来创造“对象”了,一个类可以创建多个对象,
语法格式: new 类名();
为了使用对象更加方便,一般使用变量接收一下对象,如:Student s = new Student();
需要注意的是:java 语言当中凡是使用 class关键字定义的类都属于引用数据类型,类名本身就是这种引用数据类型的类型名

2、对象的使用

创建了对象之后怎么去访问这个对象的属性呢,或者说学生对象现在有了,怎么去访问他 的学号、姓名、性别、年龄等信息呢。请看以下代码:

public class StudentTest { 
	public static void main(String[] args) { 
	//创建一个学生对象 
	Student s1 = new Student(); 
	//再创建一个学生对象 
	Student s2 = new Student(); 
	//以上代码其实和这行代码差不多 
	int i = 10;
	int no1 = s1.no; 
	System.out.println("学号:" + no1); 
	String name1 = s1.name; 
	System.out.println("姓名:" + name1); 
	int age1 = s1.age; 
	System.out.println("年龄:" + age1); 
	boolean sex1 = s1.sex; 
	System.out.println("性别:" + sex1);
	int no2 = s2.no; 
	System.out.println("学号:" + no2); 
	String name2 = s2.name; 
	System.out.println("姓名:" + name2); 
	int age2 = s2.age; 
	System.out.println("年龄:" + age2); 
	boolean sex2 = s2.sex;
	System.out.println("性别:" + sex2);
	//当然,也可以不使用no1,no2 这样的变量接收 
	System.out.println("学号 = " + s1.no); 
	System.out.println("姓名 = " + s1.name); 
	System.out.println("年龄 = " + s1.age); 
	System.out.println("性别 = " + s1.sex);
	System.out.println("学号 = " + s2.no); 
	System.out.println("姓名 = " + s2.name); 
	System.out.println("年龄 = " + s2.age); 
	System.out.println("性别 = " + s2.sex);
}

运行结果如下图所示:

通过以上的 Student 类可以创建很多学生对象,假设通过 Student 类实例化了两个学生对象,那必然会有两个不同的学号,以上程序中并没有给学号赋值,但是获取了到的学号都是0,这是怎么回事呢?这是因为在java语言当中,当实例变量没有手动赋值,在创建对象的时候,也就是说在new的时候,系统会对实例变量默认赋值, 它们的默认值请参考下表:

二、对象创建和使用的深层次解密 1.java 虚拟机内存管理


① 程序计数器: 1) 概念:可以看做当前线程所执行的字节码的行号指示器。 2) 特点:线程私有的内存
② java虚拟机栈(重点): 1) 概念:描述的是 java 方法执行的内存模型。(每个方法在执行的时候会创建一个栈帧,用于存储局部变量表, *** 作数栈,动态链接,方法出口等信息。每个方法从调用直至完成的过程,就对应一个栈帧从入栈到出栈的过程。)2) 特点:线程私有,生命周期和线程相同。这个区域会出现两种异常: StackOverflowError 异常:若线程请求的深度大于虚拟机所允许的深度。 OutOfMemoryError 异常:若虚拟机可以动态扩展,如果扩展是无法申请到足够的内存。
③ 本地方法栈: 1) 概念:它与虚拟机栈所发挥的作用是相似的,区别是 java 虚拟机栈为执行 java 方法服务,而本地方法栈是为本地方法服务。2) 特点:线程私有,也会抛出两类异常:StackOverflowError 和OutOfMemoryError。
④ java堆(重点): 1) 概念:是被所有线程共享的一块区域,在虚拟机启动时创建。 2) 特点:线程共享,存放的是对象实例(所有的对象实例和数组),GC管理的主要 区域。可以处于物理上不连续的内存空间。
⑤ 方法区(重点): 1) 概念:存储已被虚拟机加载的类信息、常量、静态变量,即时编译器编译后的代码等数据 2) 特点:线程共享的区域,抛出异常OutOfMemory异常:当方法区无法满足内存分配需求的时候。
java 虚拟机有三块主要的内存空间,分别是“虚拟机栈(后面简称栈)”、“方法区”、“堆区”,方法区存储类的信息,栈中存储方法执行时的栈帧以及局部变量,堆区中主要存储 new 出来的对象,以及对象内部的实例变量。其中垃圾回收器主要针对的是堆内存, 方法区中最先有数据,因为程序执行之前会先进行类加载。栈内存活动最频繁,因为方法不断的执行并结束,不断的进行压栈d栈 *** 作。将目前阶段需要掌握的内存空间使用一张简单的图表示出来:

在了解了Java虚拟机内存分配之后,来看看以下代码在执行过程中,内存是如何变化的:

public class StudentTest { 
	public static void main(String[] args){ 
	int i = 10; 
	Student s1 = new Student();
	} 
}

以上代码在执行过程中内存的变化情况如图所示:




2.构造方法Constructor

构造方法是类中特殊的方法,通过调用构造方法来完成对象的创建,以及对象属性的初始化 *** 作。
语法格式:

[修饰符列表] 构造方法名(形式参数列表){ 
	构造方法体;
}

① 构造方法名和类名一致。
② 构造方法用来创建对象,以及完成属性初始化 *** 作。
③ 构造方法返回值类型不需要写,写上就报错,包括void也不能写。
④ 构造方法的返回值类型实际上是当前类的类型。
⑤ 一个类中可以定义多个构造方法,这些构造方法构成方法重载。
当一个类没有显示的定义任何构造方法的时候,系统默认提供无参数构造方法,当显示的定义构造方法之后,系统则不再提供无参数构造方法。无参数构造方法又叫做缺省构造器,或者默认构造方法。 一般在开发中为了方便编程,建议程序员手动的将无参数构造方法上,因为不写无参数构造方法的时候,这个默认的构造方法很有可能就不存在了,另外也是因为无参数构造方法使用的频率较高。
一个类当中可以定义多个构造方法,构造方法是支持重载机制的,具体调用哪个构造方法,那要看调用的时候传递的实际参数列表符合哪个构造方法了。构造方法虽然在返回值类型方面不写任何类型,但它执行结束之后实际上会返回该对象在堆内存当中的内存地址,这个时候可以定义变量接收对象的内存地址,这个变量就是之前所学的“引用”,通过引用可以访问对象的内存地址。
因为所有的构造方法在执行过程中没有给对象的属性手动赋值,系统则自动赋默认值,实际上大部分情况下我们需要在构造方法中手动的给属性赋值,这本来就是构造方法的主要的职责, 要不然重载多次构造方法就没有意义了。
通过以上内容的学习得知,构造方法的作用是专门用来创建对象同时给属性赋值的,它的语法很简单,比普通方法还要简单,因为构造方法名和类名一致,还不需要写返回值类型,使用 new 就可以调用了。在一个类当中可以同时定义多个构造方法,它们之间构成重载关系。 这样就做到了在 java中你想要什么就 new什么,每一次 new都会在堆内存中创建对象,并且 对象内部的实例变量被初始化了。 一定要注意,实例变量没有手动赋值的时候统会默认赋值,但不管是手动赋值还是系统赋默认值,都是在构造方法执行的时候才会进行赋值 *** 作,类加载的时候并不会初始化实例变 量的空间,那是因为实例变量是对象级别的变量,没有对象,哪来实例变量,这也是为什么实例变量不能采用“类名”去访问的原因。

3.空指针异常

当一个空的引用去访问实例变量会出现空指针异常的问题(ava.lang.NullPointerException)。

4.方法调用时参数的传递问题

方法在调用的时候参数是如何传递的呢?其实在调用的时候参数传递给方法,这个过程就是赋值的过程,参数传递和“赋值规则”完全相同,只不过参数传递在代码上看不见“=”运 算符。先来深入的研究一下“赋值规则”。

public class AssignmentTest { 
	public static void main(String[] args){ 		
		//基本数据类型
		int a = 10; 
		int b = a; 
		//a赋值给 b,a把什么给了 b? 
		//引用数据类型 Bird bird1 = new Bird("polly"); 
		//bird1 赋值给 bird2,bird1 把什么给了 bird2?
		Bird bird2 = bird1;
		}
	}
	class Bird { 
		String name; 
		public Bird(){} 
		public Bird(String _name){ 
		name = _name;
		} 
	}

在以上程序当中,有两个疑问,第一个:a 赋值给 b,a 把什么给了 b?第二个:bird1 赋值给 bird2,bird1 把什么给了 bird2?
其实 a,b,bird1,bird2 就是 4 个普通的变量,唯一的区别只是 a 和 b 都是基本数据类型的变量,bird1 和 bird2 都是引用数据类型的变量(或者说都是引用),a 变量中保存的那个“值”是 10, bird1 变量中保存的那个“值”是 0x8888(java 对象内存地址),本质上来说 10 和 0x8888 都是“值”, 只不过一个“值”是整数数字,另一个“值”是 java 对象的内存地址,我们不要把内存地址特殊化, 它也是一个普通的值。 那么“赋值”是什么意思呢,顾名思义,赋值就是把“值”赋上去。a 赋值给 b,本质上不是把 a给了 b,而是把 a 变量中保存的“值 10”复制了一份给了 b。bird1 赋值给 bird2 本质上不是把 bird1 给了 bird2,而是把 bird1 变量中保存的“值 0x8888”复制了一份给了 bird2。请看以下内存图的变化:


通过以上内存图我们可以看出“赋值”运算的时候实际上和变量的数据类型无关,无论是
基本数据类型还是引用数据类型,一律都是将变量中保存的“值”复制一份,然后将复制的这 个“值”赋上去。他们的区别在于,如果是基本数据类型则和堆内存当中的对象无关,如果是 引用数据类型由于传递的这个值是 java 对象的内存地址,所以会导致两个引用指向同一个堆 内存中的java对象,通过任何一个引用去访问堆内存当中的对象,此对象内存都会受到影响。

总结

通过本章节内容的学习,知道了怎么创建对象,对象创建之后怎么去使用这个对象,掌握构造方法怎么定义、怎么调用。需要 理解构造方法在开发中的作用。
在本章节内容中我们尤其要对 Java 虚拟机内存管理这块要有深入的理解。要知道 Java 虚拟机中的栈和堆各自存储什么,要能够画出程序执行过程中内存的变化。要知道空指针异常是如何发生的,为什么会出现空指针。 除以上所描述之外,还需要掌握方法调用时参数是如何传递的,一定要弄明白这个知 识点,在以后的开发中会频繁的进行方法的调用,而方法调用时需要传递参数,参数传递时内是如何变化的,弄明白这些有助于我们对程序运行结果的把控。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5695311.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存