服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - Java创建对象之显示创建与隐式创建

Java创建对象之显示创建与隐式创建

2023-05-13 01:07未知服务器之家 Java教程

目录 一. 对象简介 1. 概念 2. 行为和特征 3. 对象的创建方式(重点) 3.1 显式创建 3.2 隐式创建 二. 显式创建 1. 使用new关键字创建对象 1.1 new简介 1.2 new作用 1.3 基本语法 1.4 代码案例 2. newlnstance()方法 3. clone()方法 4. readObject()方法 5. 小

目录
  • 一. 对象简介
    • 1. 概念
    • 2. 行为和特征
    • 3. 对象的创建方式(重点)
      • 3.1 显式创建
      • 3.2 隐式创建
  • 二. 显式创建
    • 1. 使用new关键字创建对象
      • 1.1 new简介
      • 1.2 new作用
      • 1.3 基本语法
      • 1.4 代码案例
    • 2. newlnstance()方法
      • 3. clone()方法
        • 4. readObject()方法
          • 5. 小结
          • 三. 隐式创建
            • 1. 给String字符串变量赋值
              • 2. “+”号拼接多个字符串
                • 3. JVM虚拟机加载类时隐式创建类对象
                  • 4. 小结
                  • 四. 对象的使用
                    • 1. 简介
                      • 2. 使用
                      • 五. 创建对象的内存分析(重点)
                        • 1. 内存简介
                          • 2. 内存分析
                          • 六. 结语

                            一. 对象简介

                            1. 概念

                            在之前的文章中,其实已经给大家解释过对象的概念了。在面向对象的编程规范中,“一切皆对象”,对象就是面向对象编程的核心。现实世界中的每一个物体都是对象!当然,这个“对象”不是你怀里撒娇的男/女朋友,而是指某个“类”的一个实例。

                            比如,“人”是一个“整体”的概念,它不是“个体”的概念,所以“人”是“类别(模板)”,而不是对象。但是在人这个“类别”中,有法外狂徒张三这个个体,张三就是一个具体的“对象”。每个对象都有自己的状态和行为,比如张三的状态有:身高、体重、爱好;行为有:吃、喝、piao、du、抽,坑、蒙、拐、骗、偷等。

                            2. 行为和特征

                            一个对象主要包括行为和特征(状态、属性)两个核心要素。

                            Java创建对象之显示创建与隐式创建

                            在这段简单的代码中,Person p1=new Person();,前半部分Person p1,表示是在内存中分配一个Person类型的变量p1。后半部分new Person();,表示利用new关键字和构造方法来创建一个Person类型的对象,Person()是构造方法的名字。当构造方法执行完,这个Person类型的对象就建造出来了,也就为其分配了对应的内存。

                            虽然p1是引用类型的变量,但p1自身会存储在栈内存中。而使用new关键字创造出来的对象,则被存储在堆内存(heap)中。且在new关键字真正创建出引用类型的对象之后,会把这个对象在内存中的地址返回给p1变量进行引用,这样我们就可以通过调用p1找到对内存中的Person对象。

                            所以Person p1=new Person();这行代码的作用就是,把Person对象在内存中的地址 赋值 给变量p1。在Java中,我们可以把p1变量叫做引用变量,或者简称为引用。又因为p1变量中存放的是引用类型的内存地址值,我们也可以把p1的值叫做引用地址。

                            2. newlnstance()方法

                            除了使用new关键字创建对象之外,我们还可以使用newInstance()方法创建对象。该方法是java.lang.Class 或 java.lang.reflect.Constuctor类中的实例方法,其语法格式如下:

                            java.lang.Class 类对象名称 = java.lang.Class.forName(要实例化的类全称);

                            类名 对象名 = (类名)Class类对象名称.newInstance();

                            我们在调用java.lang.Class类中的forName()方法时,需要将待实例化类的全限定名(如 com.yyg.Person)作为参数传递进来,然后再调用 java.lang.Class类对象的newInstance()方法创建对象。

                            /** 
                             * @author 
                             */
                            public class Demo01 {
                                public static void main(String[] args) {
                            	//newInstance()方法创建对象
                            	try {
                                        Class<?> clazz = Class.forName("com.yyg.Person");
                                        Person p2 = (Person) clazz.newInstance();
                            	} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
                                        e.printStackTrace();
                            	}
                                }
                            }
                            

                            因为这一块的内容涉及到了反射的知识点,后面会专门讲解反射,这一块的内容大家先有所了解即可。

                            3. clone()方法

                            第三种显式创建对象的方法,就是利用实例对象的clone()方法进行对象的复制,也可以创建一个新对象出来。clone()方法创建对象时,不会调用类的构造方法,它会创建一个复制的对象,这个对象和原来的对象具有不同的内存地址,但它们的属性值却相同。

                            另外clone()方法是Java Object对象中被protected修饰的方法,可供子类调用以实现子类的克隆逻辑,但不能直接调用。并且我们使用该方法创建对象时,还要求待实例化的类必须实现 java.lang.Cloneable接口,否则会抛出 java.lang.CloneNotSupportedException异常,比较麻烦,所以该方法并不常用。 clone()方法创建对象的语法格式如下:

                            类名 对象名 = (类名)已创建好的类对象名.clone();

                            4. readObject()方法

                            我们还可以使用java.io.ObjectlnputStream对象的readObject()方法来创建一个新对象。ObjectlnputStream是IO流中的内容,以后会详细讲解Java中的IO流,大家对此先有一个大致的印象即可。

                            5. 小结

                            在上面给大家提到了4种显式创建对象的方式,在此我们进行一个小小的总结:

                            • new关键字是最常用的创建对象方式;
                            • 使用 new关键字 或 Class对象的newInstance()方法 创建对象时,都会调用类的构造方法;
                            • 使用 Class类的newInstance()方法 创建对象时,会调用类的默认构造方法,即无参构造方法;
                            • 使用 Object类的clone()方法 创建对象时,不会调用此类的构造方法,只会创建一个复制出的对象,该对象和原来的对象具有不同的内存地址,但它们的属性值相同;
                            • 如果类没有实现Cloneable接口却调用它的clone()方法,会抛出 java.lang.CloneNotSupportedException异常。

                            三. 隐式创建

                            在Java中,除了可以显式地创建对象之外,还可以隐式地创建对象。隐式创建对象主要是通过以下几种方式:

                            • 给String字符串变量赋值;
                            • “+”号拼接多个字符串;
                            • JVM虚拟机加载类时隐式创建类对象。

                            1. 给String字符串变量赋值

                            我们经常给一个字符串变量赋值,如下所示:

                            String str = "Hello,壹哥";
                            

                            上面的str变量,其实就是一个String对象,该对象会由JVM虚拟机隐式地创建出来。

                            2. “+”号拼接多个字符串

                            我们知道,“+”运算符有两个基本作用:加法运算和字符串拼接。当进行字符串拼接时,其运算的结果是一个新的 String对象,示例如下:

                            String str1 = "Hello";
                            String str2 = "一一哥";
                            String str3 = str1+str2;    // str3引用一个新的String对象
                            

                            通过上面的语句,JVM会隐式地创建出第3个String对象。

                            3. JVM虚拟机加载类时隐式创建类对象

                            当Java的JVM虚拟机加载一个类时,会隐式地创建出一个可以描述这个类的Class实例对象。类的加载是指把类的.class字节码文件读到内存中,把它存放到运行时数据区的方法区中,然后会在堆区创建一个 java.lang.Class对象,用来封装类在方法区内的数据结构。

                            4. 小结

                            无论我们是釆用显式或是隐式方式创建对象,Java虚拟机都会在创建对象时包含以下步骤:

                            • 给对象分配内存;
                            • 将对象的实例变量自动初始化成该变量类型的默认值;
                            • 初始化对象,给实例变量赋予正确的初始值。

                            四. 对象的使用

                            1. 简介

                            我们在通过一系列方式创建好对象之后,那么这个对象该怎么用呢?我们知道对象中有状态和行为两个核心要素,那怎么来调用一个对象的行为和状态呢?Java中,一个普通的实例对象调用它的行为和状态,基本的语法格式如下:

                            //调用状态

                            对象.属性名;

                            //调用方法

                            对象.方法名();

                            接下来我们通过一个小案例给大家展示一下。

                            2. 使用

                            /** 
                            * @author 
                            */
                            public class Demo02 {
                                public static void main(String[] args) {
                                    // 对象的使用
                            	//先创建一个对象
                            	Person p1=new Person();
                            		
                            	//调用对象的属性(该属性不能是私有的,否则别的类中无法看到)--状态.
                            	String name = p1.name;
                            		
                            	//调用对象的方法
                            	p1.eat();
                            	p1.speak("一一哥", "男", 18);
                                }
                            }
                            

                            大家要注意,当我们在A类中调用B类对象时,B类对象的属性或方法不能是私有的,否则在A类中会无法看到该属性或方法。

                            五. 创建对象的内存分析(重点)

                            1. 内存简介

                            Java程序在运行时,操作系统会给程序分配三块主要的内存空间:栈内存、堆内存、方法区

                            • 栈内存: 栈内存也叫做虚拟机栈,可以存放基本类型的数据和引用类型的地址,主要是局部变量。 这些 局部变量存放了编译期可知长度的各种基本数据类型和对象引用,方法执行完就会自动释放。栈内存具有先进后出、占用空间比较小、存取速度相对较快的特点。
                            • 堆内存: 堆内存中可以存放各对象实例(所有new出来的对象都是)和数组都在堆中存放,即堆中存放的是引用类型的实际数据。 堆内存占用的空间比较大,存取速度相对较慢。
                            • 方法区: 方法区主要用于存储类信息、常量、静态变量,静态代码块、即时编译器(JIT Compiler)编译后的代码数据等 简单言之就是存储类的结构信息。类的结构信息包括类的名称、方法信息、字段信息等。在方法区中,有一块空间叫做常量池(串池),用来存放字符串常量。还有一块空间叫做静态区,用来存储静态变量等静态数据。但在JDK 7之后,常量池、静态区作为堆中的一个子部分,方法区的概念被弱化。

                            2. 内存分析

                            /**
                            * @author 
                            */
                            public class Demo02 {
                                public static void main(String[] args) {
                                    // 对象的使用
                            	//先创建一个Person对象
                            	Person p1=new Person();
                                    p1.name="一一哥";
                                    p1.age=18;
                                    p1.sex="男";
                            
                                    //创建p2对象
                                    Person p2=new Person();
                                }
                            }
                            

                            在上述代码中,我们定义的Person类型p1变量实际上是一个引用,它会被存放在栈内存中,而存放实际数据的Person对象则存放在堆内存中。如下图所示:

                            Java创建对象之显示创建与隐式创建

                            根据上面的内存分析图可知:

                            • Person类中包含了name、age、sex三个属性,它们分别是String、int、String类型。我们知道,它们的默认值分别是null、0、null。
                            • 我们创建一个p1对象之后,p1会被存放在栈区,然后p1会通过堆中Person对象的内存地址,去找到该对象被实例化的内容(即name、age、sex等)。
                            • Java代码中刚创建出来的对象属性都是采用默认值(null、0、null),等我们通过"对象.属性"的方式对属性进行重新赋值后,堆内存中存储的才是赋值后的内容。
                            • 我们创建的另一个对象p2,p2依然在栈区,但并没有对p2进行初始化,所以p2的属性在堆内存中都是默认值。
                            • 堆内存中的每一个对象,都有一个独立的内存空间。

                            六. 结语

                            至此,就给大家把Java的对象介绍完毕了,现在你知道几种创建对象的方式呢?最后再跟大家说一下,不管我们用哪种方式创建出来的对象,每个对象都是相互独立的。这些不同的对象在内存中会占有独立的内存地址,且每个对象都具有自己的生命周期。当一个对象的生命周期结束时,对象就变成了垃圾,这些垃圾对象会被JVM虚拟机自带的GC垃圾回收机制来处理。

                            以上就是Java创建对象之显示创建与隐式创建的详细内容,更多关于Java创建对象的资料请关注其它相关文章!

                            原文地址:https://juejin.cn/post/7207078219216322618

                            延伸 · 阅读

                            精彩推荐