unity创建和销毁对象
本文是我们名为“ 高级Java ”的学院课程的一部分。
本课程旨在帮助您最有效地使用Java。 它讨论了高级主题,包括对象创建,并发,序列化,反射等。 它将指导您完成Java掌握的旅程! 在这里查看 !
目录
- 1.简介 2.实例构建
- 2.1。 隐式(生成)构造函数 2.2。 没有参数的构造函数 2.3。 带参数的构造函数 2.4。 初始化块 2.5。 施工保证 2.6。 能见度 2.7。 垃圾收集 2.8。 终结者
3.静态初始化 4.施工模式 - 4.1。 辛格尔顿 4.2。 实用程序/助手类 4.3。 厂 4.4。 依赖注入
5.下载源代码 6.接下来
1.简介
根据TIOBE编程社区索引 ,Java编程语言起源于Sun Microsystems,于1995年发布,是世界上使用最广泛的编程语言之一。 Java是一种通用编程语言。 它对软件开发人员的吸引力主要归功于其强大的库和运行时,简单的语法,丰富的受支持平台集(一次编写,随时随地运行– WORA)和强大的社区。
在本教程中,我们将介绍高级Java概念,并假设我们的读者已经对该语言有所了解。 它绝不是完整的参考,而是将Java技能提升到更高水平的详细指南。
在整个过程中,将有很多代码片段需要研究。 在有意义的地方,将使用Java 7语法和Java 8 one来提供相同的示例。
2.实例构建
Java是面向对象的语言,因此,创建新的类实例(对象)可能是其最重要的概念。 构造函数在新类实例初始化中起着核心作用,而Java提供了一些定义它们的方法。
隐式(生成)构造函数
Java允许定义一个没有任何构造函数的类,但这并不意味着该类将没有任何构造函数。 例如,让我们考虑这个类:
package com.javacodegeeks.advanced.construction;public class NoConstructor {
}
该类没有构造函数,但是Java编译器将隐式生成一个构造函数,并且可以使用new
关键字创建新的类实例。
final NoConstructor noConstructorInstance = new NoConstructor();
没有参数的构造函数
没有参数的构造函数(或no-arg构造函数)是显式完成Java编译器工作的最简单方法。
package com.javacodegeeks.advanced.construction;public class NoArgConstructor {public NoArgConstructor() {// Constructor body here}
}
使用new
关键字创建类的新实例后,将调用此构造函数。
final NoArgConstructor noArgConstructor = new NoArgConstructor();
带参数的构造函数
带参数的构造函数是参数化新类实例创建的最有趣,最有用的方法。 下面的示例定义一个带有两个参数的构造函数。
package com.javacodegeeks.advanced.construction;public class ConstructorWithArguments {public ConstructorWithArguments(final String arg1,final String arg2) {// Constructor body here}
}
在这种情况下,当使用new
关键字创建类实例时,应同时提供两个构造函数参数。
final ConstructorWithArguments constructorWithArguments = new ConstructorWithArguments( "arg1", "arg2" );
有趣的是,构造函数可以使用特殊的this
关键字相互调用。 链式构造函数被认为是一种好习惯,因为它可以减少代码重复并基本上导致具有单个初始化入口点。 例如,让我们添加另一个仅带有一个参数的构造函数。
public ConstructorWithArguments(final String arg1) {this(arg1, null);
}
初始化块
Java还有另一种使用初始化块提供初始化逻辑的方法。 很少使用此功能,但最好知道它的存在。
package com.javacodegeeks.advanced.construction;public class InitializationBlock {{// initialization code here}
}
以某种方式,初始化块可能被视为匿名的无参数构造函数。 特定的类可能具有多个初始化块,并且它们都将按照在代码中定义的顺序被调用。 例如:
package com.javacodegeeks.advanced.construction;public class InitializationBlocks {{// initialization code here}{// initialization code here}}
初始化块不能代替构造函数,可以与它们一起使用。 但是要提到的一点很重要,那就是初始化块总是在任何构造函数之前调用。
package com.javacodegeeks.advanced.construction;public class InitializationBlockAndConstructor {{// initialization code here}public InitializationBlockAndConstructor() {}
}
施工保证
Java提供了开发人员可能依赖的某些初始化保证。 未初始化的实例和类(静态)变量将自动初始化为其默认值。
类型 | 默认值 |
布尔值 | 假 |
字节 | 0 |
短 | 0 |
整型 | 0 |
长 | 0升 |
烧焦 | \ u0000 |
浮动 | 0.0分 |
双 | 0.0天 |
对象参考 | 空值 |
表格1
让我们确认使用以下类作为简单示例:
package com.javacodegeeks.advanced.construction;public class InitializationWithDefaults {private boolean booleanMember;private byte byteMember;private short shortMember;private int intMember;private long longMember;private char charMember;private float floatMember;private double doubleMember;private Object referenceMember;public InitializationWithDefaults() { System.out.println( "booleanMember = " + booleanMember );System.out.println( "byteMember = " + byteMember );System.out.println( "shortMember = " + shortMember );System.out.println( "intMember = " + intMember );System.out.println( "longMember = " + longMember );System.out.println( "charMember = " + Character.codePointAt( new char[] { charMember }, 0 ) );System.out.println( "floatMember = " + floatMember );System.out.println( "doubleMember = " + doubleMember );System.out.println( "referenceMember = " + referenceMember );}
}
使用new
关键字实例化后:
final InitializationWithDefaults initializationWithDefaults = new InitializationWithDefaults(),
以下输出将显示在控制台中:
booleanMember = false
byteMember = 0
shortMember = 0
intMember = 0
longMember = 0
charMember = 0
floatMember = 0.0
doubleMember = 0.0
referenceMember = null
能见度
构造函数服从Java可见性规则,并且可以具有访问控制修饰符,该修饰符确定其他类是否可以调用特定的构造函数。
修饰符 | 包 | 子类 | 其他所有人 |
上市 | 无障碍 | 无障碍 | 无障碍 |
受保护的 | 无障碍 | 无障碍 | 无法访问 |
<无修饰符> | 无障碍 | 无法访问 | 无法访问 |
私人的 | 无法访问 | 无法访问 | 无法访问 |
表2
垃圾收集
Java(尤其是JVM)使用自动垃圾收集。 简而言之,无论何时创建新对象,都会自动为其分配内存。 因此,只要不再引用这些对象,它们就会被销毁并回收其内存。
Java垃圾回收是世代相传的,它基于以下假设:大多数对象都死于年轻对象(它们在创建后不久就不再被引用,因此可以安全地销毁)。 大多数开发人员过去都认为Java中的对象创建速度很慢,因此应尽可能避免实例化新对象。 实际上,事实并非如此:用Java创建对象既便宜又快速。 不过,昂贵的是不必要地创建了长期存在的对象,这些对象最终可能会填满旧的对象并导致世界各地的垃圾回收。
终结者
到目前为止,我们已经讨论了构造函数和对象初始化,但实际上并没有提及任何与之对应的东西:对象破坏。 这是因为Java使用垃圾回收来管理对象的生命周期,垃圾回收器负责破坏不必要的对象并回收内存。
但是,Java中有一个特殊的功能称为终结器 ,该终结器有点类似于析构函数,但具有执行资源清除的不同目的。 终结器被认为是一个危险的功能(这会导致许多副作用和性能问题)。 通常,它们不是必需的,应该避免使用(非常罕见的情况除外,这些情况大多与本机对象有关)。 终结器的更好替代方案是Java 7语言构造引入的,称为try-with-resources和AutoCloseable
接口,该接口允许编写干净的代码,如下所示:
try ( final InputStream in = Files.newInputStream( path ) ) {// code here
}
3.静态初始化
到目前为止,我们已经研究了类实例的构造和初始化。 但是Java也支持称为静态初始值设定项的类级初始化构造。 除了附加的static
关键字外,它们与初始化块非常相似。 请注意,每个类加载器仅执行一次静态初始化。 例如:
package com.javacodegeeks.advanced.construction;public class StaticInitializationBlock {static {// static initialization code here}
}
与初始化块类似,您可以在类定义中包括任意数量的静态初始化器块,它们将按照它们在代码中出现的顺序执行。 例如:
package com.javacodegeeks.advanced.construction;public class StaticInitializationBlocks {static {// static initialization code here}static {// static initialization code here}
}
因为可以从多个并行线程触发静态初始化块(当第一次加载该类时),所以Java运行时保证它只能以线程安全的方式执行一次。
4.施工模式
多年来,Java社区中出现了一些易于理解且广泛适用的构造(或创建)模式。 我们将介绍其中最著名的:单例,助手,工厂和依赖注入(也称为控制反转)。
辛格尔顿
Singleton是软件开发人员社区中最古老且有争议的模式之一。 基本上,其主要思想是确保在任何给定时间只能创建该类的单个实例。 但是,如此简单,单例引发了很多有关如何使其正确,尤其是线程安全的讨论。 这是朴素的单例类的样子:
package com.javacodegeeks.advanced.construction.patterns;public class NaiveSingleton {private static NaiveSingleton instance;private NaiveSingleton() { }public static NaiveSingleton getInstance() {if( instance == null ) {instance = new NaiveSingleton();}return instance;}
}
此代码的至少一个问题是,如果由多个线程并发调用,它可能会创建该类的许多实例。 正确设计单例(但以非延迟方式)的一种方法是使用类的static
final
属性。
final property of the class.
package com.javacodegeeks.advanced.construction.patterns;public class EagerSingleton {private static final EagerSingleton instance = new EagerSingleton();private EagerSingleton() { }public static EagerSingleton getInstance() {return instance;}
}
如果您不想浪费资源,并且希望在真正需要时懒惰地创建单身人士,则需要显式同步,这有可能导致多线程环境中的并发性降低(有关Java并发性的更多详细信息,请参见本教程的第9部分 , 并发最佳实践 )。
package com.javacodegeeks.advanced.construction.patterns;public class LazySingleton {private static LazySingleton instance;private LazySingleton() { }public static synchronized LazySingleton getInstance() {if( instance == null ) {instance = new LazySingleton();}return instance;}
}
如今,在大多数情况下,单例并不被认为是一个不错的选择,主要是因为它们使代码很难测试。 依赖项注入模式的主导(请参阅下面的“ 依赖项注入”部分)也使单例成为不必要。
实用程序/助手类
实用程序或帮助程序类是许多Java开发人员使用的非常流行的模式。 基本上,它代表了非实例化类(与构造函数声明为private
),可选声明为final
(有关声明类的更多详细信息final
将在本教程的第3部分提供, 如何设计类和接口 ),包含static
方法只要。 例如:
package com.javacodegeeks.advanced.construction.patterns;public final class HelperClass {private HelperClass() { }public static void helperMethod1() {// Method body here}public static void helperMethod2() {// Method body here}
}
从经验丰富的软件开发人员的角度来看,此类帮助程序通常成为各种不相关方法的容器,这些方法没有找到其他放置位置,但应以某种方式共享并由其他类使用。 在大多数情况下,应避免此类设计决策:始终可以找到另一种方法来重用所需的功能,同时保持代码的简洁明了。
厂
事实证明,工厂模式在软件开发人员手中是极其有用的技术。 因此,它具有Java的几种风格,从工厂方法到抽象工厂 。 工厂模式的最简单示例是static
方法,该方法返回特定类的新实例( factory方法 )。 例如:
package com.javacodegeeks.advanced.construction.patterns;public class Book {private Book( final String title) {} public static Book newBook( final String title ) { return new Book( title );}
}
有人可能会认为引入newBook
工厂方法没有多大意义,但使用这种模式通常会使代码更具可读性。 工厂模式的另一个变体涉及接口或抽象类( 抽象工厂 )。 例如,让我们定义一个工厂接口 :
public interface BookFactory {Book newBook();
}
根据库类型,有几种不同的实现:
public class Library implements BookFactory {@Overridepublic Book newBook() {return new PaperBook();}
}public class KindleLibrary implements BookFactory {@Overridepublic Book newBook() {return new KindleBook();}
}
现在, Book
的特定类隐藏在BookFactory
接口实现的后面,仍然提供了创建书籍的通用方法。
依赖注入
依赖注入(也称为控制反转)被认为是类设计人员的一种好习惯:如果某个类实例依赖于其他类实例,则应通过构造函数(或setter,策略)为其提供(注入)那些依赖。等),但不是由实例本身创建的。 让我们考虑以下示例:
package com.javacodegeeks.advanced.construction.patterns;import java.text.DateFormat;
import java.util.Date;public class Dependant {private final DateFormat format = DateFormat.getDateInstance();public String format( final Date date ) {return format.format( date );}
}
Dependant
类需要一个DateFormat实例,它只是在构造时通过调用DateFormat.getDateInstance()
创建一个实例。 更好的设计是使用构造函数参数执行相同的操作:
package com.javacodegeeks.advanced.construction.patterns;import java.text.DateFormat;
import java.util.Date;public class Dependant {private final DateFormat format;public Dependant( final DateFormat format ) {this.format = format;}public String format( final Date date ) {return format.format( date );}
}
在这种情况下,该类的所有依赖关系都是从外部提供的,因此更改日期格式并为其编写测试用例非常容易。
5.下载源代码
- 您可以在此处下载源代码: com.javacodegeeks.advanced.java
6.接下来
在本教程的这一部分中,我们研究了类和类实例的构造和初始化技术,以及涵盖了几种广泛使用的模式的方法。 在下一部分中,我们将剖析Object
类及其知名方法的用法: equals
, hashCode
, toString
和clone
。
翻译自: https://www.javacodegeeks.com/2015/09/how-to-create-and-destroy-objects.html
unity创建和销毁对象