JAVA-对象的创建和使用

PS:类体中的成员变量又被称作实例变量、对象变量,因为这一类成员变量位于类体中,表示一种状态信息,该类变量只能依赖于具体的实例(对象)而存在,而不是依赖于一个抽象概念(类),这些变量的值对于每个对象来说又可能是不一样的,如果想要访问到正确的信息,应该通过每个对象去进行访问,所以我们称之为实例变量,因为对象又称之为实例,所以实例变量又被我们称之为对象变量,可以理解为对象级别的变量,依赖于对象的变量。该类变量,只有在创建了具体的对象之后,才会为其分配内存,并隶属于某对象。

1、对象的创建

        关键字:new,一种运算符,用于创建对象并在jvm的堆内存中为该对象开辟新的内存空间。

        语法结构:类名 对象名=new 类名(可选的参数);

        ——对象所占用的内存是在堆内存中分配的,通过该语句,一个类可以实例化n个对象。

2、分析对象创建语句

以学生类Student为例,如果想要创建对象,java语句如下:

        Student  stu=new Student();

        这里stu其实是一个局部变量,局部变量是存放在栈内存中的。

        真正的实例化该类并为其在JVM的堆内存中分配空间的是new Student(),所以这才是我们所说的真正的对象;

        那么stu是什么呢?一个存储在栈内存中的局部变量,我们一般称之为引用,该局部变量用于接收new出来的内存单元的地址,即对象的内存单元的地址,也可以说该引用指向对象所在的内存单元,但是要知道stu并不是对象,它只是一个指向它的引用,存储了内存地址的局部变量。

        例如:

public class Computer {
    String name;
    String style;
    String color;
}
import java.util.Scanner;
public class test3 {
    public static void main(String[] args) {
        Computer computer=new Computer();
        System.out.println("电脑品牌是:"+computer.name);
        computer.name="联想";
        System.out.println("电脑品牌是:"+computer.name);
    }
}

        输出结果如下:

电脑品牌是:null
电脑品牌是:联想

进程已结束,退出代码为 0

内存分布图如下:

        程序运行分析:

        类进行加载,由类加载器将字节码文件加载到内存空间当中,当程序开始运行,执行到某个方法的时候,会在栈内存中逐一进行压栈,运行结束后弹栈释放内存空间并结束运行,所以这里当遇到main方法时,该方法在栈内存中分配内存空间进行压栈, 之后执行实例化类Computer的语句,当语句执行时,会先在JVM的堆内存中开辟一块内存空间,并分配给该对象,并将该块内存单元的地址赋值给存储在栈内存中的局部变量(引用)comuter,我们可以说引用computer指向了地址为0X1234的内存单元,也可以理解为引用和对象是代表的同一个内存单元。

        从输出结果可以看出,computer引用所代表的对象的name完成了赋值的操作,进行输出后,我们发现值改变了,我们尝试其他的访问方式,可以发现是无法正确访问的,因为这些状态信息和动作信息只有通过对象,才算有意义,才可以正确的访问。

import java.util.Scanner;

public class test3 {
    static int sum=0;
    static int n=0;
    public static void main(String[] args) {
        Computer computer=new Computer();
        System.out.println("电脑品牌是:"+computer.name);
        computer.name="联想";
        System.out.println("电脑品牌是:"+Computer.name);  //类名·变量名
    }
}
D:\Idea\JAVATEST\src\test3.java:107:45
java: 无法从静态上下文中引用非静态 变量 name

        如果想要访问堆内存中的某对象的数据信息,只能通过创建的存储着该块内存变量地址的引用进行访问,屏蔽了C语言中指针的概念,程序员是无法对堆内存进行直接操作的。访问数据的语法格式如下,以变量的访问为例,“·” 可以理解为常规意义 “的”;

读取值:引用.变量名;

修改数据:引用.变量名=新值;

        注意引用类型String类,在使用过程中我们可以发现,一般字符串定义都是如下:

String  a="abcd";

        可以发现String类型的对象并没有利用new关键词去创建,而是直接进行了赋值的操作,因为其内存的分配无需用new关键字,是自动的进行内存分配的,所以上文中的内存分布图其实可以理解为:

         对Computer类型的对象的状态信息name进行赋值时的操作,理论上隐含一个String对象的创建和对象内存的一个赋值操作,是将一个String类型的变量的地址,赋值给了局部变量(引用)name。

        注意:对象是一种引用数据类型的变量,其存储的不是常规的基本数据类型的值,而是某内存单元的地址,如果未进行人为的赋值,它的默认的初始值为NULL,而不是0,相当于C语言中的空指针的概念。

3、引用类型变量使用

        引用数据类型和基本数据类型身份是相当的,不用进行特殊化的处理,统一看作”数据类型“处理。

        所以引用数据类型变量的定义是可以在类体中充当实例变量的,这种定义的方式可以有效地交代各实体之间的复杂关系。相对的关系之间也更加的直观,更加的容易理解。

        例如:学生和电脑两个类之间,每个类都具有各自实体抽象出来的多项共同特征

public class Student {
    String sno;  //学号
    String sname;  //姓名
    Computer myCom;   //电脑
}
public class Computer {
    String name;   //电脑名称
    String style;   //电脑款式
    String color;  //电脑颜色
}

        在学生类中有一个Computer引用类型的局部变量myCom,用于在创建电脑对象后指向该对象的内存单元,这样表示的是电脑和学生实体之间的关系,如果在Student类当中,只定义一个变量comName,关系表示的并不是很明确,并且对于信息的表示和获取都不方便,并且上述定义方式,二者之间的关联相对灵活,后者关联会更强一些。

        主方法如下:

//主方法
public class test04 {
    public static void main(String[] args) {
        Student stu1=new Student();
        stu1.sno="1705113137";
        stu1.sname="张梦";
        stu1.myCom=new Computer();
        stu1.myCom.name="联想";
        stu1.myCom.color="black";
        stu1.myCom.style="@123";

        System.out.println("学生"+stu1.sname+"的电脑为"+stu1.myCom.name+"的品牌");
    }
}

        当创建Computer类型的对象时,将新的对象的内存单元的地址赋值给了Student类中的引用myCom,这样引用指向的是一个具有多种信息的复杂的对象,可以通过学生对象进行合理的调用,找到它所关联的Computer对象,并访问到全部的相关信息。

        在对信息进行访问时,同样采用”·“运算符,从引用开始,逐层引用,例如如上的程序,其内存分布图如下:

        因为程序员不能直接的对堆内存进行访问和使用的,所以通过引用stu1来实现,通过引用stu1,可以访问到Student类型的对象内存,而通过该内存中存放的局部变量引用,可以访问到Computer类型的对象的内存单元,这样其实在Student和Computer对象之间就实现了一个关联。

        对对象信息的访问有时候相对灵活,根据引用和对象之间的关系合理调用即可。

4、常见错误

        空指针的异常:

Exception in thread "main" java.lang.NullPointerException
	at test04.main(test04.java:7)

进程已结束,退出代码为 1

        来看一下代码的变化,我们讲stu1所指向的Student类型对象内存单元的Computer引用并没有和Computer对象的内存单元产生关联,即表示该引用并不存在任何的实际意义

public class test04 {
    public static void main(String[] args) {
        Student stu1=new Student();
        stu1.sno="1705113137";
        stu1.sname="张梦圆";
                      //stu1.myCom=new Computer();
        stu1.myCom.name="联想";
        stu1.myCom.color="black";
        stu1.myCom.style="@123";

        System.out.println("学生"+stu1.sname+"的电脑为"+stu1.myCom.name+"的品牌");
    }
}

        在内存分析中,是这样的,myCom的引用断开,即该引用为空,并且因为java中垃圾回收机制的存在,Computer类型对象的内存单元会被垃圾回收。

         总的来说,当空的引用访问实例相关的数据时,一定会产生空指针异常,其中实例相关的数据,指的就是如果要访问该信息时,一定要通过对象进行访问,才可以正常的访问到正确的信息。在引用时,注意这种嵌套关系,认真一些。

5、回顾

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值