精华内容
下载资源
问答
  • 2018-12-28 17:23:27
    • 类的基本结构

           如果一切都是对象,那么是什么决定某一类对象的行为与外观呢?答案时“类”。类是构造对象的模板或蓝图。就像建筑物与设计图纸,通过一份设计图纸,可以构造处建筑物,而Java开发人员在编写代码时,实际上是编写类代码,对象只有程序运行时才存在。

           当用户创建一个Java程序时,可以通过类声明来定义类。通常,这些类里没有main方法,只有一些属性和方法。一个完整的程序,应该由若干个类组成,其中一般只有一个类有main方法。

    在Java中,最简单的类的定义语法为:

    class 类名

    {

           //类中的代码

    }

    第一行称为类的声明。两个花括号之间的部分称为类体,类体中可以包含方法或成员变量。

    例如下面代码定义了一个简单的类Student。

    class  Student   { .......}

    在具体的编程中,一个完整的类还包含构造函数、成员变量、方法等,将在后面逐一介绍。


    • 类之间的关系

    在面向对象的思想中,类之间存在一下几种常见的关系

    1、USES-A 关系

          “USES-A 关系” 是一种最明显、最常见的关系,若类A中的方法操纵了类B(对象)的成员,则称之为类A “USES-A” (用到了)类B。例如,汽车启动前检查汽油是否足够,例:

    class Car
    {
    	private int cubage=100;
    	
    	public void startIsEnough()
    	{
    		if(cubage>80)
    			System.out.println("汽油充足,汽车可以启动");
    		else 
    			System.out.println("汽车不可以启动");
    	}
    
    }
    public class Sample3_1 
    {	
    	public static void main(String[] args) 
    	{
    		// TODO Auto-generated method stub
    		Car c=new Car();
    		c.startIsEnough();
    
    	}
    
    }
    

           在上述例子中,main方法实例化Car类后,调用startIsEnough()方法,形成“IS-A”关系。因为汽油储量设备为100,满足储备量充足规则,可以启动,所以运行结果中打印了”汽油充足,可以启动”。

     

    2、HAS-A关系

    “HAS-A”关系是一种拥有关系,若类A中有B类型的成员引用变量,则类A“HAS-A”(即拥有)类型B。例如,轿车拥有轮胎:

    class Car
    {
    	private Type t=new Type();
    	
    	public Type getTypeInfo()
    	{
    		return t;
    	}
    }
    class Type 
    {
    	private String material="橡胶" ;
    	private String color="黑色" ;
    	
    	public String getMaterial()
    	{
    		return material;
    	}
    	
    	public String getColor()
    	{
    		return color;
    	}
    }
    public class Sample3_2 
    {
    
    	public static void main(String[] args) 
    	{
    		// TODO Auto-generated method stub
    		Car c=new Car();
    		System.out.println("轮胎的颜色为:"+c.getTypeInfo().getColor());
    		System.out.println("轮胎的材料为:"+c.getTypeInfo().getMaterial());
    	}
    
    }
    

    通过上述代码可以看出“HAS-A”关系的具体含义,由于汽车对象拥有了轮胎对象,所以汽车对象也就拥有了轮胎对象中的一切可见信息。

     

    3、IS-A关系

              在面向对象中“IS-A”的概念是基于继承的, 旨在表达一个类是另一个类的子类。也就是说,若类A是类B子类的一种,则可以说类A  “IS-A”(是一种)类B。例如,“苹果”是“水果”的一种,则他们之间的关系为“苹果” IS-A(是一种)“水果”。

            在实际开发中需要同时用到以上介绍的几种关系,要抓住现实世界中事物之间的实际关系来进行抽象,然后再Java世界中建立模型。如果搞错了关系的类型,有可能影响系统的开发或维护。


    • 构造函数

            在创建对象时,对象的成员可以由构造函数方法进行初始化。构造函数是一种特殊的方法,它具有和他所在的类完全一样的名字。一旦定义好一个构造函数,创建对象时就会自动调用它。构造函数没有返回类型,这是因为一个类的构造函数的返回值就是这个类本身。构造函数的任务就是初始化以一个对象的内部状态,所以用new操作符创建一个实例后,立刻就会得到一个可用的对象。例如,利用构造函数初始化汽车的各项参数:

    package Car;
    class Car
    {
    	private String color;
    	private String brand;
    	
    	//下面为构造函数,构造函数与类名相同。在构造函数中,初始化汽车的颜色和品牌
    	public Car()
    	{
    		this.color="黑色";
    		this.brand="大众";
    	}
    	
    	//构造方法
    	public String getColor()
    	{
    		return this.color;
    	}
    	public String getBrand()
    	{
    		return this.brand;
    	}
    }
    public class Sample3_3 
    {
    
    	public static void main(String[] args) 
    	{
    		// TODO Auto-generated method stub
    		Car c=new Car();
    		System.out.println("汽车的颜色为:"+c.getColor());
    		System.out.println("汽车的品牌为:"+c.getBrand());
    	}
    
    }
    

           在上面的例子中,main方法实例化Car类时,调用Car类的构造函数初始化类变量。在Car类中,构造函数是不包含任何参数的。有时也需要为构造函数定义参数,方便赋值,下面的例子同时定义了两个构造函数,分别带参数和不带参数:

    package Car;
    class Car
    {
    	private String color;
    	private String brand;
    	
    	//无参构造函数
    	public Car()
    	{
    		this.color="黑色";
    		this.brand="大众";
    	}
    	
    	//有参构造函数
    	public Car(String co ,String br )
    	{
    		this.color=co;
    		this.brand=br;
    	}
    	
    	//构造方法
    	public String getColor()
    	{
    		return this.color;
    	}
    	public String getBrand()
    	{
    		return this.brand;
    	}
    }
    public class Sample3_3 
    {
    
    	public static void main(String[] args) 
    	{
    		// TODO Auto-generated method stub
    		Car c1=new Car();
    		System.out.println("汽车的颜色为:"+c1.getColor());
    		System.out.println("汽车的品牌为:"+c1.getBrand());
    		
    		Car c2=new Car("红色","奥迪");
    		System.out.println("汽车的颜色为:"+c2.getColor());
    		System.out.println("汽车的品牌为:"+c2.getBrand());
    
    	}
    
    }
    

    上面说的例子当中,包含两个构造函数,有时一个类可能有多个构造函数,每个构造函数的参数类型均不相同,多个构造函数可看作方法的重载,只能根据参数类型匹配合适的构造函数。但构造方法与普通方法不同,是一种特殊的方法,具体有以下特点:

    1. 构造方法的方法名必须与类名相同
    2. 构造方法没有返回类型,也不能定义为void,在方法名面前不声明方法类型
    3. 构造方法的主要作用是完成对象的初始化工作,它能够把定义对象时的参数传给对象的域
    4. 构造方法不能由编程人员调用,而要系统调用
    5. 构造方法可以重载,以参数的个数,类型或排列顺序区分
    6. 一个类可以定义多个构造方法,如果在定义类时没有定义构造方法,则编译系统会自动插入一个无参的默认构造器,这个构造器不执行任何代码

    • 类成员

    定义了类之后,就可以在类体中声明两种类的成员,成员变量与成员方法。

    1、成员变量的使用

           成员变量就是类的属性,类定义中的属性指定了一个对象区别于其他对象的值。例如,学生类的定义包括年龄、姓名和班级这些属性,每个对象的这些属性都有自己的值。所有由类定义建立的对象都共享类的方法,但是,它们都具有各自属性变量的副本。

           成员变量有时也可以称为实例变量,其定义写在类体中:

    class Student
    {
    	public int stuAge;
    	public String stuName;
    	public String stuClass; 
    	//年龄,姓名,班级
    }
    public class Sample3_5 
    {	
    	public static void main(String[] args) 
    	{
    		// TODO Auto-generated method stub
    		Student s1=new Student();
    		Student s2=new Student();
    
    		//为s1赋值
    		s1.stuAge=21;
    		s1.stuName="张三";
    		s1.stuClass="200801";
    		
    		//为s2赋值
    		s2.stuAge=23;
    		s2.stuName="李四";
    		s2.stuClass="200802";
    		
    		System.out.println(s1.stuName+' '+s1.stuAge+' '+s1.stuClass);
    		System.out.println(s2.stuName+' '+s2.stuAge+' '+s2.stuClass);
    	}
    
    }
    

           有点像C语言中的结构体,从上述例子中可以看出,两个对象成员变量有其各自的值,互不影响,new操作创建对象后将返回其引用值,一般在new操作完成后都将其返回的对象引用赋值给一个引用,也就是让引用指向创建的对象。如果只是用new操作创建对象不让某个引用指向该对象,则对象自创建后就不能对其进行访问了。因为在Java中,访问对象只能通过指向对象的引用来实现。

     

    2、成员变量的初始值

    变量类型默认值
    booleanfalse
    char'\u000'
    byte0
    short0
    int0
    long0L
    float0.0F
    double0.0D
    对象引用型null

           对象引用型成员变量,其初始值为null,表示此引用没有指向任何对象,这里需要注意的是,字符串(String)类型空引用(null)与空字符串不同,空引用表示没有指向任何对象,而空字符串表示内容为空的字符串对象。


    • 对象的创建

           有了类就可以利用其创建对象了,在Java中创建对象很简单,只要用new关键字即可,由类创建对象的过程中称为实例化,每个对象是类的一个实例,如学生类是对什么是学生做定义,而张三、李四是学生类的实例。

           创建对象与基本类型的声明类似,首先说明创建对象的所属类名,然后为对象的名称,例如 Student s=new Student();Student 为对象所属类,s为对象名称,通过new为新对象创建内存空间。与变量相比,对象的内存控件要大很多,因为对象是以类为模板创建的具体实列,具有属性和方法,例如s对象具有班级、姓名等属性,具有上课、下课等方法。如果要调用该对象则需要用点运算符' . '连接需要的属性和方法,例如s.name=“李四”;。

     

     

     

     

     

     

     

     

     

    更多相关内容
  • Unity3D 用对象创建对象

    千次阅读 2020-03-19 16:00:57
    在 Unity3d 中可以使用 GameObject.Instantiate 的方式从一个 GameObject 里面创建一个和这个 GameObject 一样的对象 一般此时游戏对象都是使用模板对象,在 Unity3d 里面制作一个模板是十分简单的,只需要在 ...

    在 Unity3d 中会用到从一个游戏对象复制出一个新的游戏物体的方式,如制作射击游戏的子弹等。在 Unity3d 中可以使用 GameObject.Instantiate 的方式从一个 GameObject 里面创建一个和这个 GameObject 一样的对象

    一般此时游戏对象都是使用模板对象,在 Unity3d 里面制作一个模板是十分简单的,只需要在 Hierarchy 里面的物体拖动放到 Assets 文件夹里面就可以了

    拖放进去的模板对象推荐给他一个命名,这样才方便查找

    先点击 Hierarchy 然后点击菜单的 GameObject 的创建,创建一个立方体。接下来将这个立方体拖动放到 Assets 文件夹,删除 Hierarchy 里面的立方体。等等,是不是有更加简洁的步骤?没错,在 Assets 文件夹里面右击也是可以创建的,只是在 Hierarchy 创建的时候可以方便看到对象在游戏中显示的好看还是不好看

    新建一个 C# 代码,可以命名为 Create 在这个代码里面将会判断如果用户点击了按键,将会创建一个 Cube 立方体

    在 Unity3d 中判断用户按键的方式请看 Unity3d 连续按键处理和单次按键处理

    从 VisualStudio 打开代码,或者右击刚才创建出来的代码文件点击 Open 都可以

    在 C# 代码里面添加一个公开的字段,这个字段叫 Cube 用来在 Unity3d 界面给他赋值

        public GameObject Cube;

    创建出来的代码还需要放在某个 GameObject 里面才能运行,本文将这个代码放在相机里面,放在相机可以通过拖动代码文件,放在相机对象上面,此时可以在相机里面看到如下图

    可以在相机的 Component 看到有脚本代码,所以反过来点击 Add Component 添加代码也是可以的

    在这个代码里面可以看到刚才定义的字段 Cube 在界面显示,将刚才放在 Assets 的 Cube 对象拖动放在这个字段上去,这样就在 Unity 上绑定了游戏对象了

    也就是在脚本执行的时候,这个 Cube 字段就会被框架赋值,给的值就是在 Unity 界面拖动过去的对象

    接下来就是编辑 Update 的方法了,在判断到用户点击了鼠标,就根据字段创建一个新的游戏对象,这里创建的游戏对象默认都会自动添加到游戏画面中

        void Update()
        {
            if (Input.GetButtonDown("Fire1"))
            {
                // 鼠标左键
                var cube = GameObject.Instantiate(Cube);
            }
        }

    此时就完成了创建,保存代码,在 Unity3d 里面点击开始游戏,然后点击一下鼠标。此时可能还看不到这个 cube 对象,可能的原因就是这个 Cube 不在相机范围内。可以通过点击一下暂停按钮看看是不是 Cube 放在了相机范围外

    如果想要设置这个 Cube 在相机可见范围里面,简单做法是放在相机前面,我的相机是面向 z 轴的,如下图我的相机设置如下,那么如何设置创建出来的物体的坐标在我的相机前面

    可以通过物体的 transform 属性进行移动物体,可以先移动到相机所在的地方,然后再次移动到相机前面

            if (Input.GetButtonDown("Fire1"))
            {
                // 鼠标左键
                var cube = GameObject.Instantiate(Cube);
                cube.transform.Translate(transform.position);
                cube.transform.Translate(0, 0, 10);
            }

    这样就完成了代码啦

    本文代码放在github欢迎小伙伴访问

    我搭建了自己的博客 https://blog.lindexi.com/ 欢迎大家访问,里面有很多新的博客。只有在我看到博客写成熟之后才会放在csdn或博客园,但是一旦发布了就不再更新

    如果在博客看到有任何不懂的,欢迎交流,我搭建了 dotnet 职业技术学院 欢迎大家加入

    如有不方便在博客评论的问题,可以加我 QQ 2844808902 交流

    知识共享许可协议
    本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

    展开全文
  • Java创建对象的四种方式

    万次阅读 多人点赞 2016-05-09 16:47:56
     一旦获取了该类所对应的Class对象之后,就可以通过调用Class对象的方法来获得该对象和该类的真实信息了。 一.new出一个对象 二.利用反射创建对象 1.创建对象     通过反射来...

    1.new
    2.clone
    3.newInstance
    4.反序列化
    5.String s = "abc"(这个是比较特殊的)

    以String类为例

    String sring = null;

     

      Class class1 = String.class;// 该方法最为安全可靠,程序性能更高。
      Class class2 = string.getClass();
      Class class3 = Class.forName("java.lang.String");// 可能抛出ClassNotFoundException异常

     

      一旦获取了该类所对应的Class对象之后,就可以通过调用Class对象的方法来获得该对象和该类的真实信息了。



    一.new出一个对象

    二.利用反射创建对象

    1.创建对象 

     

      通过反射来生成对象有如下两种方式:

    (1)使用Class对象的newInstance()方法来创建该Class对象对应类的实例。但是这种方式要求该Class对象的对应类有默认的构造器,而执行newInstance()方法时实际上是利用默认构造器来创建该类的实例。

    (2)先使用Class对象获取指定的Constructor对象,再调用Construtor对象的newInstance()方法来创建该Class对象对应类的实例。通过这种方式可以选择使用某个类的指定构造器来创建实例。

     

      另外,如果我们不想利用默认构造器来创建java对象,而想利用指定的构造器来创建java对象,则需要利用Construtor对象,每个Construtor对应一个构造器,为了利用指定构造器来创建java对象,需要如下三个步骤:

    (1)获取该Class对象;

    (2)利用该Class对象的getConstrutor方法来获取指定的构造器; 

    (3)调用Construtor的newInstance方法来创建Java对象。

     

    2.调用方法

     

      获取到某个类的Class对象之后,可以通过该Class对象的getMethods方法或者getMethod方法获取全部或指定方法。

      每个Method对象对应一个方法,获得Method对象后,程序就可通过该Method来调用对应的方法,在Method里包含一个invoke方法,该方法签名如下:

      Object invoke(Object obj,Object... args);该方法中的obj是执行该方法的主调,后面的args是执行该方法时传入该方法的实参。

      当通过Method的invoke方法来调用对应的方法时,Java会要求程序必要要有调用该方法的权限。如果程序确实需要调用该对象的私有方法,则可先调用Method对象的:

      setAccessible(boolean flag);方法,将Method对象的accessoble标志设置为指示的布尔值。

      布尔值为true,则表示该Method在使用时应该取消Java语言访问权限检查;

      布尔值为false,则表示该Method在使用时应该实施Java语言访问权限检查;

     

    3.访问属性值

     

      通过Class对象的getFields或getField方法可以获取该类所包括的全部Field(属性)或指定Field,Field提供了如下两组方法来访问属性:

      getXxx(Object obj);获取obj对象该Field的属性值,此处的Xxx对应8个基本类型,如果该属性的类型是引用类型则取消get后面的Xxx。

      setXxx(Object obj,Xxx val);将obj对象的该Field设置成val值,此处的Xxx对应8个基本类型,如果该属性的类型是引用类型则取消set后面的Xxx。

     

    4示例代码如下:

    import java.lang.reflect.Constructor;
    import java.lang.reflect.Method;
    public class ClassTest {
        public static void main(String[] args) throws Exception {
            Object object;
            Class cl = Class.forName("TestMe");
            Method method = cl
                    .getDeclaredMethod("print", new Class[]{String.class});
            Constructor constructor = cl
                    .getDeclaredConstructor(new Class[]{String.class});
            object = constructor.newInstance(new Object[]{"Hello"});
            method.invoke(object, new Object[]{"zhouxianli"});
        }
    }
    class TestMe {
        private String str;
        public TestMe(String str) {
            this.str = str;
            System.out.println("In Constructor str = " + str);
        }
        public void print(String name) {
            System.out.println("In print str = " + str + " and name = " + name);
        }
    } 

    三.利用反序列化创建对象

    1、为什么要进行序列化

    再介绍之前,我们有必要先了解下对象的生命周期,我们知道Java中的对象都是存在于堆内存中的,而堆内存是可以被垃圾回收器不定期回收的。从对象被创建到被回收这一段时间就是Java对象的生命周期,也即Java对象只存活于这个时间段内。

    对象被垃圾回收器回收意味着对象和对象中的成员变量所占的内存也就被回收,这意味着我们就再也得不到该对象的任何内容了,因为已经被销毁了嘛,当然我们可以再重新创建,但这时的对象的各种属性都又被重新初始化了。所以如果我们需要保存某对象的状态,然后再在未来的某段时间将该对象再恢复出来的话,则必须要在对象被销毁即被垃圾回收器回收之前保存对象的状态。要保存对象状态的话,我们可以使用文件、数据库,也可以使用序列化,这里我们主要介绍对象序列化。我们很有必要了解这方面的内容,因为对象序列化不仅在保存对象状态时可以被用到(对象持久化),在Java中的远程方法调用RMI也会被用到,在网络中要传输对象的话,则必须要对对象进行序列化,关于RMI有机会我会再专门开贴介绍。

    简单总结起来,进行对象序列化的话的主要原因就是实现对象持久化和进行网络传输,这里先只介绍怎样通过对象序列化保存对象的状态。

    下面我们通过一个简单的例子来介绍下如何进行对象序列化。

    2、怎样进行对象序列化

    假设我们要保存Person类的某三个对象的nameageheight这三个成员变量,当然这里只是简单举例

    我们先看下Person类,要序列化某个类的对象的话,则该类必要实现Serializable接口,从Java API中我们发现该接口是个空接口,即该接口中没声明任何方法。

    import java.io.Serializable;  
    public class Person implements Serializable {  
    int age;  
    int height;  
    String name;  
    public Person(String name, int age, int height){  
    this.name = name;  
    this.age = age;  
    this.height = height;  
    }  
    }  
    下面我们看一下如何来进行序列化,这其中主要涉及到 Java I/O 方面的内容,主要用到两个类 FileOutputStream ObjectOutputStream FileOutputStream 用于将字节输出到文件, ObjectOutputStream 通过调用 writeObject 方法将对象转换为可以写出到流的数据。所以整个流程是这样的: ObjectOutputStream 将要序列化的对象转换为某种数据,然后通过 FileOutputStream 连接某磁盘文件,再对象转化的数据转化为字节数据再将其写出到磁盘文件。下面是具体代码:
    import java.io.FileOutputStream;  
    import java.io.IOException;  
    import java.io.ObjectOutputStream;  
    public class MyTestSer {  
    /** 
     * Java对象的序列化与反序列化 
     */  
    public static void main(String[] args) {  
    Person zhangsan = new Person("zhangsan", 30, 170);  
    Person lisi = new Person("lisi", 35, 175);  
    Person wangwu = new Person("wangwu", 28, 178);  
    try {  
    //需要一个文件输出流和对象输出流;文件输出流用于将字节输出到文件,对象输出流用于将对象输出为字节  
    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("person.ser"));  
    out.writeObject(zhangsan);  
    out.writeObject(lisi);  
    out.writeObject(wangwu);  
    out.close();  
    } catch (IOException e) {  
    e.printStackTrace();  
    }  
    }  
    }  
    3、对象的反序列化

    我们存储的目的主要是为了再恢复使用,下面我们来看下加上反序列化后的代码:

    import java.io.FileInputStream;  
    import java.io.FileOutputStream;  
    import java.io.IOException;  
    import java.io.ObjectInputStream;  
    import java.io.ObjectOutputStream;  
    public class MyTestSer {  
    /** 
     * Java对象的序列化与反序列化 
     */  
    public static void main(String[] args) {  
    Person zhangsan = new Person("zhangsan", 30, 170);  
    Person lisi = new Person("lisi", 35, 175);  
    Person wangwu = new Person("wangwu", 28, 178);  
    try {  
    //需要一个文件输出流和对象输出流;文件输出流用于将字节输出到文件,对象输出流用于将对象输出为字节  
    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("person.ser"));  
    out.writeObject(zhangsan);  
    out.writeObject(lisi);  
    out.writeObject(wangwu);  
    } catch (IOException e) {  
    e.printStackTrace();  
    }  
    try {  
    ObjectInputStream in = new ObjectInputStream(new FileInputStream("person.ser"));  
    Person one = (Person) in.readObject();  
    Person two = (Person) in.readObject();  
    Person three = (Person) in.readObject();  
    System.out.println("name:"+one.name + " age:"+one.age + " height:"+one.height);  
    System.out.println("name:"+two.name + " age:"+two.age + " height:"+two.height);  
    System.out.println("name:"+three.name + " age:"+three.age + " height:"+three.height);  
    } catch (Exception e) {  
    e.printStackTrace();  
    }  
    }  
    }  
    输出结果如下:
    name:zhangsan age:30 height:170  
    name:zhangsan age:35 height:175  
    name:zhangsan age:28 height:178  
    从添加的代码我们可以看到进行反序列化也很简单,主要用到的流是FileInputstreamObjectInputstream正好与存储时用到的流相对应。另外从结果顺序我们可以看到反序列化后得到对象的顺序与序列化时的顺序一致。

    4、总结

    进行对象序列化主要目的是为了保存对象的状态(成员变量)。

    进行序列化主要用到的流是FileOutputStreamObjectOutputStreamFileOutputStream主要用于连接磁盘文件,并把字节写出到该磁盘文件;ObjectOutputStream主要用于将对象写出为可转化为字节的数据。

    要将某类的对象序列化,则该类必须实现Serializable接口,该接口仅是一个标志,告诉JVM该类的对象可以被序列化。如果某类未实现Serializable接口,则该类对象不能实现序列化。

    保存状态的目的就是为了在未来的某个时候再恢复保存的内容,这可以通过反序列化来实现。对象的反序列化过程与序列化正好相反,主要用到的两个流是FileInputstreamObjectInputStream

    反序列化后得到的对象的顺序与保存时的顺序一致。

    5、补充

    补充一:上面我们举得例子很简单,要保存的成员变量要么是基本类型的要么是String类型的。但有时成员变量有可能是引用类型的,这是的情况会复杂一点。那就是当要对某对象进行序列化时,该对象中的引用变量所引用的对象也会被同时序列化,并且该对象中如果也有引用变量的话则该对象也将被序列化。总结说来就是在序列化的时候,对象中的所有引用变量所对应的对象将会被同时序列化。这意味着,引用变量类型也都要实现Serializable接口。当然其他对象的序列化都是自动进行的。所以我们只要保证里面的引用类型是都实现Serializable接口就行了,如果没有的话,会在编译时抛出异常。如果序列化的对象中包含没有实现Serializable的成员变量的话,这时可以使用transient关键字,让序列化的时候跳过该成员变量。使用关键字transient可以让你在序列化的时候自动跳过transient所修饰的成员变量,在反序列化时这些变量会恢复到默认值。

    补充二:如果某类实现了Serializable接口的话,其子类会自动编程可序列化的,这个好理解,继承嘛。

    补充三:在反序列化的时候,并不会调用对象的构造器,这也好理解,如果调用了构造器的话,对象的状态不就又重新初始化了吗。

    补充四:我们说到对象序列化的是为了保存对象的状态,即对象的成员变量,所以静态变量不会被序列化。


    四.clone创建对象

    什么是"clone"? 

      在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能 会需要一个和A完全相同新对象B,并且此后对B任何改动都不会影响到A中的值,也就是说,A与B是两个独立的对象,但B的初始值是由A对象确定的。在 Java语言中,用简单的赋值语句是不能满足这种需求的。要满足这种需求虽然有很多途径,但实现clone()方法是其中最简单,也是最高效的手段。 

       Java的所有类都默认继承java.lang.Object类,在java.lang.Object类中有一个方法clone()。JDK API的说明文档解释这个方法将返回Object对象的一个拷贝。要说明的有两点:一是拷贝对象返回的是一个新对象,而不是一个引用。二是拷贝对象与用 new操作符返回的新对象的区别就是这个拷贝已经包含了一些原来对象的信息,而不是对象的初始信息。 

      1. Clone&Copy
         假设现在有一个Employee对象,Employee tobby =new Employee(“CMTobby”,5000),通
    常我们会有这样的赋值Employee cindyelf=tobby,这个时候只是简单了copy了一下reference,cindyelf和tobby都指向内存中同一个object,这样cindyelf或者tobby的一个操作都可能影响到对方。打个比方,如果我们通过cindyelf.raiseSalary()方法改变了salary域的值,那么tobby通过getSalary()方法得到的就是修改之后的salary域的值,显然这不是我们愿意看到的。我们希望得到tobby的一个精确拷贝,同时两者互不影响,这时候我们就可以使用Clone来满足我们的需求。Employee cindy=tobby.clone(),这时会生成一个新的Employee对象,并且和tobby具有相同的属性值和方法。
          2. Shallow Clone&Deep Clone
    Clone是如何完成的呢?Object在对某个对象实施Clone时对其是一无所知的,它仅仅是简单地执行域对域的copy,这就是Shallow Clone。这样,问题就来了咯,以Employee为例,它里面有一个域hireDay不是基本型别的变量,而是一个reference变量,经过Clone之后就会产生一个新的Date型别的reference,它和原始对象中对应的域指向同一个Date对象,这样克隆类就和原始类共享了一部分信息,而这样显然是不利的,过程下图所示:

     

    这个时候我们就需要进行deep Clone了,对那些非基本型别的域进行特殊的处理,例如本例中的hireDay。我们可以重新定义Clone方法,对hireDay做特殊处理,如下代码所示:

    [java]  view plain  copy
     print ?
    1.    class Employee implements Cloneable  
    2.   
    3. {  
    4.         public Object clone() throws CloneNotSupportedException  
    5.         {  
    6.          Employee cloned = (Employee) super.clone();  
    7.       cloned.hireDay = (Date) hireDay.clone()  
    8.       return cloned;  
    9.         }  
    10. }  

     

    3. Clone()方法的保护机制

    在Object中Clone()是被申明为protected的,这样做是有一定的道理的,以Employee

    类为例,通过申明为protected,就可以保证只有Employee类里面才能“克隆”Employee对象,原理可以参考我前面关于public、protected、private的学习笔记。

    4. Clone()方法的使用

    Clone()方法的使用比较简单,注意如下几点即可:

    a. 什么时候使用shallow Clone,什么时候使用deep Clone,这个主要看具体对象的域是什么性质的,基本型别还是reference variable

    b. 调用Clone()方法的对象所属的类(Class)必须implements Clonable接口,否则在调用Clone方法的时候会抛出CloneNotSupportedException。








    展开全文
  • 此刻正在翻阅这篇文章的你,一定是一个爱学习的人儿!奥利给! 有同学在学习String类的相关知识以后,产生了这样的疑问:...答案:String对象一旦创建,实体是不可以变化的,即内容不能再修改 我们来看一个例子: ...
    此刻正在翻阅这篇文章的你,一定是一个爱学习的人儿!奥利给!
    

    有同学在学习String类的相关知识以后,产生了这样的疑问:String类创建的字符串对象可以更改吗?
    答案:String对象一旦创建,实体是不可以变化的,即内容不能再修改
    我们来看一个例子:

    public class Study{
    	public static void main(String args[ ]) {      
    		Study1 study = new Study1();  //创建引用对象study
    		study.fun();   //调用fun()方法
    	}
    }
    class Study1{
    	void fun() {
    		String h1 = "helloWorld";
    		System.out.println("第一次的h1= "+h1);
    		h1="Java";
    		System.out.println("修改之后的h1= "+h1);
    	}
    }
    

    结果显示:
    在这里插入图片描述
    过程分析:在这里我定义了String类型的变量h1,随后对其变量值进行更改,得到不同的结果。String类创建的字符串对象都存放在Heap(堆)中,而第二次经过修改的字符串内容变了,这说明h1的指向变了,但第一个字符串对象还存在于堆中,即此时堆中存在了两个字符串,如下图:
    在这里插入图片描述
    而后等到某个时间段,某些没用到的对象就会被JVM中的垃圾回收器检测出来并回收。简单来说,String声明的是一个引用地址,而不是对其进行赋值。若果你要对其字符串进行修改等操作,那这个时候StringBuffer就派上用场了!

    有疑问欢迎留言

    点个赞,加个关注呗!嘿嘿!

    展开全文
  • UML、对象创建型模式

    万次阅读 2019-12-03 21:02:20
    UML 关联关系(Association) 是类与类之间最常用的一种关系, 它是一种结构...一种使用关系,例如类A的某个方法需要类B做参数,即要使用类B的方法,用虚线表示 聚合关系(Aggregation) 表示一个整体与部分的关系,成...
  • java-匿名对象

    千次阅读 2021-02-26 20:14:33
    概念创建对象时,只有创建对象的语句,却没有把对象地址值赋值给某个变量。虽然是创建对象的简化写法,但是应用场景非常有限。1. 创建匿名对象直接调用方法,没有变量名。newScanner(System.in).nextInt();2. 一旦...
  • java.lang.Class类和反射机制创建对象

    万次阅读 2015-11-24 00:12:02
    java.lang.Class类  Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时...Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。  Class 没有公共构造方法。Class 对象
  • 深入理解工厂模式——由对象工厂生成对象

    万次阅读 多人点赞 2018-05-27 20:12:45
    如果创建某个对象的过程都很复杂,需要一定的代码量,而且很多地方都要用到,那么就会有很多的重复代码。 (3) 降低维护成本 :由于创建过程都由工厂统一管理,所以发生业务逻辑变化,不需要找到所有需要创建...
  • 开源对象存储MinIO技术白皮书

    万次阅读 多人点赞 2019-09-27 13:38:36
    某个对象、某个桶、整个集群。 在控制台上执行mc命令即开始进行数据修复。该命令一方面向minio发送数据修复的HTTP请求,另一方面不断地接收minio服务进程返回的修复进度信息,而后输出到控制台,直到修复工作完毕...
  • Qt Quick 组件与对象动态创建详解

    万次阅读 多人点赞 2014-06-24 08:22:55
    通常我们可以根据这个原则来选择将一个 Component 定义在哪里:如果一个 Component 比较小且只在某个 qml 文档中使用或者一个 Component 从逻辑上看从属于某个 qml 文档,那就可以采用嵌入的方式
  • java对象的默认值

    千次阅读 2021-03-05 11:18:15
    2.4.1 字段和方法定义一个类时(我们在Java里的全部工作就是定义类、制作那些类的对象以及将消息发给那些对象),可在自己的类里设置两种类型的元素:数据成员(有时也叫“字段”)以及成员函数(通常叫“方法”)。...
  • 如何正确的创建和销毁Java对象

    万次阅读 2017-06-15 18:24:16
    Java是一门强大的高级语言。在学习了其基础知识,我们仍需要理解其深刻的内涵。接下来,我们会以《Effective Java》一书做为Java进阶学习的载体,对Java进行一个系统的、全新的认识。...第一章:创建和销毁对象
  • 文章目录《C++面向对象程序设计》✍千处细节、万字总结一、面向对象程序设计二、C++基础2.1 C++的产生和特点2.2 一个简单的C++示例程序2.3 C++在非面向对象方面对C语言的扩充输入和输出cinconst修饰符void型指针内联...
  • JavaScript 进阶教程(1)--面向对象编程

    万次阅读 多人点赞 2020-08-16 18:13:37
    1 学习目标 理解面向对象开发思想 掌握 JavaScript 面向对象开发相关模式 ...当实物被抽象成对象,实物之间的关系就变成了对象之间的关系,从而就可以模拟现实情况,针对对象进行编程。 (2) 对象是一个.
  • C++类和对象详解

    千次阅读 多人点赞 2020-05-08 00:43:54
    创建对象 两种创建对象的方式:一种是在栈上创建,形式和定义普通变量类似;另外一种是在堆上使用 new 关键字创建,必须要用一个指针指向它,读者要记得 delete 掉不再使用的对象。 通过对象名字访问成员使用点号....
  • java面向对象

    万次阅读 多人点赞 2018-08-21 16:51:59
    包括面向对象概念、类与对象的关系、封装、构造函数、this关键字、static关键字、单例设计模式、继承、多态、内部类、异常、包等java基础知识。 1、面向对象 面向对象是相对面向过程而言 面向对象和面向过程都是...
  • 将Java对象写入文件中

    万次阅读 多人点赞 2018-06-05 00:01:39
    Java对象序列化 首先介绍一下对象序列化的目标:对象序列化的目标是将对象保存到磁盘中,或允许在网络中直接传输对象。...如果需要需要让某个对象支持序列化机制,则必须让它的类是可序列化的(serializa...
  • 【C++】C++类和对象、构造函数和析构函数

    千次阅读 多人点赞 2018-06-03 20:32:37
    它即可包含描述事物的数据,又可包含处理这些数据的函数,类在程序运行时是被用作样板来建立对象的。所以要建立对象,首先必须定义类。 定义类 定义一个类的一般格式为: class 类名{ private: 成员表1; public:...
  • Java引用对象

    万次阅读 2018-12-11 10:09:03
    简介 在写了15年C/C++之后,我于1999年开始写Java。借助指针切换(pointer handoffs)等编码实践或者Purify等工具,我认为...在我不需要再管理内存我才意识到之前耗费了多少精力。 接着我就遇到了第一个OutOfMemor...
  • 重新认识java(一) ---- 万物皆对象

    万次阅读 多人点赞 2016-11-27 21:39:37
    如果你现实中没有对象,至少你在java世界里会有茫茫多的对象,听起来是不是很激动呢?
  • Java对象的生命周期

    千次阅读 2019-06-26 00:11:16
    对象创建一般需要使用new关键字,将创建对象存储在堆上(heap)。而在线程栈中会保留一个指向堆上地址的引用。 下图将展示堆栈之间的具体关系,栈中被分割成一个一个的栈帧(“frames”),其中包含调用树中每个...
  • Java-面向对象

    千次阅读 2020-02-14 16:14:48
    如果不使用static修饰,则这些方法属于该类的对象,我们得先创建对象再调用方法,在开发中工具对象只需要一份即可,可能创建N个对象,此时我们往往把该类设计为单例的.,但是还是有点麻烦. 所以,一般的,在开发中设计工具...
  • C++面向对象基础

    万次阅读 多人点赞 2018-05-20 12:40:59
    面向对象基础面向对象三大特性封装性:数据和代码捆绑在一起,避免外界干扰和不确定性访问。封装可以使得代码模块化。优点:确保用户代码不会无意间破坏封装对象的状态被封装的类的具体实现细节可以随时改变,而无须...
  • 面向对象编程的思想

    万次阅读 热门讨论 2020-09-12 16:12:00
    面向对象思想 前言        计算机的革命起源于机器,所以说,编程语言的产生也是始于对机器的模仿。在19世纪的早期就已经出现过计算机的雏形。那时,人们为了构建导航所需的表格对...
  • VB对象的事件和方法

    千次阅读 2020-09-15 12:44:45
    事件是指对象对于外部动作的响应,当对象发生了某个事件,就会执行相应的代码,这段代码被称为“事件过程”。 事件是Visual Basic预先编辑好的并且能够被对象识别的的动作,VB采用的是事件驱动机制,当用户触发了...
  • 1. Master 集群的控制节点,负责整个集群的管理和控制,kubernetes的...kube-apiserver:资源增删改查的入口kube-controller-manager:资源对象的大总管kube-scheduler:负责资源调度(Pod调度)etcd Server:kubern
  • Java面向对象(知识点整理)

    万次阅读 多人点赞 2021-02-22 08:53:55
    文章目录面向对象类与对象匿名对象创建对象的内存分析栈(stack)堆(heap)方法区PC寄存器本地方法栈内部类成员内部类局部内部类匿名内部类静态内部类包装类拆箱和装箱操作字符串转换基本数据类型和包装类型的区别...
  • 多线程(一):创建线程和线程的常用方法

    万次阅读 多人点赞 2018-09-01 19:14:23
    假如十件事情,两个人来完成,每个人在某个时间点各自做各自的事情,互不影响 并发:将一个操作分割成多个部分执行并且允许无序处理,假如有十件事情,如果有一个人在做,这个人可能做一会这个不想做了,再去做别的...
  • SQL Server 2012 创建数据库

    万次阅读 多人点赞 2019-04-15 00:06:01
    文章目录基本概念使用SSMS工具创建使用SQL语言创建 基本概念 主要数据文件(.mdf)     主要数据文件包含数据库的启动信息,并指向数据库中的其他文件,用户数据和对象可存储在此文件中,一个数据库只有一个...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 313,714
精华内容 125,485
关键字:

一旦某个对象创建后