Java学习 | 面向对象 | 对象的创建和使用

本文详细介绍了Java中类的定义、对象的创建以及内存空间的使用,包括实例变量和局部变量的区别,对象间的引用关系,以及空指针异常的情况。通过示例展示了对象在堆内存中的存储和栈内存中的引用,强调了垃圾回收机制对于不再被引用的对象进行回收的重要性。
摘要由CSDN通过智能技术生成

定义类(只定义属性)

// Student.java
// Java中所有的类都属于引用数据类型,数据类型名为类名
// 定义一个公开的类,类名为Student,即数据类型为Student
public class Student{
	//类体 = 属性 + 方法
    
	// 属性描述的是对象的状态信息,通常采用变量的方式来定义
    
    int no;		// 学号
	/*
	虽然所有学生都有学号信息,但是每一个学生的学号是不同的
	所以要访问这个学号必须先创建对象,通过对象去访问学号信息
	id变量定义在类体当中,方法体之外,这种变量称为成员变量
	学号信息不能直接通过类去访问,所以这种变量是成员变量中的实例变量
	对象又被称为实例,实例变量又被称为对象变量,即对象级别的变量
	不创建对象,id变量的内存空间是不存在的,只有创建对象后,这个id变量的内存空间才会创建
	*/
    
    String name;	// 名字
    boolean sex;	// 性别
    byte age;		// 年龄
    String address;	// 住址
    
    // 方法描述的是对象的动作信息
}
javac Student.java		// 生成Student.class

创建对象(局部变量的引用)

// 测试类,OOTest01.java
public class OOTest01{
	public static void main(String[] args){
		// int是基本数据类型,i是局部变量的变量名,10是int类型的字面值
		int i = 10;

		// Student是引用数据类型,s是局部变量的变量名,new Student()是一个学生对象
		/*
		new是一个运算符,作用是创建对象,是在JVM的堆内存中开辟一块新的内存空间用于存储对象
		new Student()是一个对象,保存在JVM堆内存中
		s是一个局部变量,保存在JVM栈内存中
		s这个变量保存的是对象在堆内存中的内存地址,这种变量称为引用,所以Student是一个引用数据类型
		*/
		Student s = new Student();

		// 访问实例变量的语法格式
		// 读取数据:引用.实例变量名
		// 修改数据:引用.实例变量名 = 值

		// 成员变量没有赋值的话,系统会赋默认值
		/*
			数据类型					默认值
			-------------------------------------
			基本数据类型
			byte,short,int,long			0
			float,double				0.0
			boolean						false
			char						\u0000
			引用数据类型
			String						null
			Student						null
		*/

		System.out.println("学号 = " + s.no);		// null
		System.out.println("姓名 = " + s.name);		// null
		System.out.println("性别 = " + s.sex);	// false
		System.out.println("年龄 = " + s.age);		// 0
		System.out.println("住址 = " + s.address);	// null

		s.no = "10";
		s.name = "jack";
		s.sex = true;
		s.age = 20;
		s.address = "北京";

		System.out.println("学号 = " + s.no);		// 12345
		System.out.println("姓名 = " + s.name);		// Jack
		System.out.println("性别 = " + s.sex);	// true
		System.out.println("年龄 = " + s.age);		// 20
		System.out.println("住址 = " + s.address);	// 北京

		// 再实例化一个全新的对象
		//Student是变量的数据类型
		//stu是一个引用,同时也是一个局部变量
		Student stu = new Student();

		System.out.println("学号 = " + stu.no);			// null
		System.out.println("姓名 = " + stu.name);		// null
		System.out.println("性别 = " + stu.sex);		// false
		System.out.println("年龄 = " + stu.age);		// 0
		System.out.println("住址 = " + stu.address);	// null
	}
}

在这里插入图片描述

实例变量的引用

// 家庭住址类,Address.java
public class Address{
	String city;		// 城市
	String street;		// 街道
	String zipcode;		// 邮编
}
// 用户类,User.java
public class User{
	// 用户编号
	// int是一种基本数据类型,即整数型
	// no是用户变量中的实例变量
	int no;	

	// 用户名
	// String是一种引用数据类型,代表字符串
	// name是用户变量中的实例变量,同时也是引用
	String name;

	// 用户住址
	// Address是一种引用数据类型,代表家庭住址
	// addr是用户变量中的实例变量,同时也是引用
	Address addr;
}
// 测试类,OOTest02.java
public class OOTest02{
	public static void main(String[] args){
		// User是引用数据类型
		// u是一个局部变量,是一个引用
		// u中保存了User对象在堆内存中的内存地址
		User u = new User;

		// 输出User对象内部实例变量的值
		System.out.println(u.no);	// 0
		System.out.println(u.name);	// null
		System.out.println(u.addr);	// null

		// 修改User对象内部实例变量的值
		u.no = 110;					// 110是一个int类型的字面值
		u.name = "jack";			// "jack"是一个String对象
		u.addr = new Address();		// new Address()是一个Address对象

		// 在main方法中只有u一个引用,因此一切都只能通过u来访问
		System.out.println(u.name + "居住在哪个城市:" + u.addr.city);		// null
		System.out.println(u.name + "居住在哪个街道:" + u.addr.street);	// null
		System.out.println(u.name + "邮编:" + u.addr.zipcode);			// null

		u.addr.city = "北京";
		u.addr.street = "朝阳";
		u.addr.zipcode = "100000";
	}
}

在这里插入图片描述

局部变量的引用和实例变量的引用指向同一个对象

// 测试类,OOTest03.java
public class OOTest03{
	public static void main(String[] args){

		// u是局部变量,同时也是引用
		User u = new User();

		// 上一个版本编写的
		// u.addr = new Address();

		// a是局部变量,同时也是引用
		Address a = new Address();
		u.addr = a;

		System.out.println(u.addr.city);	// null

		a.city = "天津";

		System.out.println(u.addr.city);	// 天津
	}
}

在这里插入图片描述

实例变量的引用相互指向对方的对象

// 丈夫类,Husband.java
public class Husband{
	// 身份证号码
	String idCard;

	// 丈夫对象中含有妻子引用
	Wife w;
}
// 妻子类,Wife.java
public class Wife{
	// 身份证号码
	String idCard;

	// 妻子对象中含有丈夫引用
	Husband h;
}
// 测试类,OOTest04.java
public class OOTest04{
	public static void main(String[] args){
		// 创建一个丈夫对象
		Husband huangXiaoMing = new Husband();
		huangXiaoMing.name = "黄晓明";

		// 创建一个妻子对象
		Wife baby = new Wife();
		baby.name = "baby";

		// 结婚(通过丈夫能找到妻子,通过妻子也能找到丈夫)
		huangXiaoMing.w = baby;
		baby.h = huangXiaoMing;

		// 得到黄晓明妻子的名字
		// 这种方式说明不了baby是黄晓明的妻子,因为有没有结婚这一步结果都是一样的
		System.out.println(huangXiaoMing.name + "妻子的名字叫" + baby.name);

		// 这种方式才能说明baby是黄晓明的妻子
		System.out.println(huangXiaoMing.name + "妻子的名字叫" + huangXiaoMing.w.name);

	}
}

在这里插入图片描述

内存空间分析总结

  • 变量类型

    • 局部变量(在方法体内声明)
    • 成员变量(在类体内方法体外声明)
      • 静态变量(修饰符有static)
      • 实例变量(修饰符没有static)

    引用可以是局部变量,也可以是成员变量

  • 三块内存空间

    • JVM(Java虚拟机)主要包括三块内存空间:方法区内存、栈内存、堆内存

    • 三块内存中,变化最频繁的是栈内存,最先出现数据的是方法区内存,垃圾回收器主要针对的是堆内存

    • 方法区内存和堆内存各1个,栈内存可以有多个(一个线程一个)

    • 方法区内存

      • 方法区内存中存储类的代码片段,在类加载的时候这些代码片段会载入
      • 静态变量存储在方法区内存中
    • 栈内存

      • 栈内存中存储方法体中的局部变量

      • 方法调用的时候,该方法所需要的内存空间在栈内存中分配,称为压栈;

        方法执行结束后,该方法所占用的内存空间释放,称为弹栈

    • 堆内存

      • 堆内存中存储Java对象
      • 对象内部的实例变量存储在堆内存中
  • 垃圾回收器(自动垃圾回收机制,GC机制)

    • 当堆内存中的Java对象变成垃圾数据时,会被垃圾回收器回收

    • 当没有任何一个引用指向该对象时,该对象就成为垃圾数据

      访问对象只能通过引用的方式,一旦没有任何引用指向对象,该对象就无法被访问

空指针异常

// 顾客类
public class Customer {
	int id;
}
// 测试类
public class Test {
	public static void main(String[] args) {
		Customer c = new Customer();
		System.out.println(c.id);	//0

		c = null;

		// 以下程序编译可以通过,因为符合语法
		// 运行出现空指针异常。
		// 空引用访问实例相关的数据一定会出现空指针异常
		// java.lang.NullPointerException
		System.out.println(c.id);
	}
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值