unity创建和销毁对象
本文是我们名为“ 高级Java ”的学院课程的一部分。
本课程旨在帮助您最有效地使用Java。 它讨论了高级主题,包括对象创建,并发,序列化,反射等。 它将指导您完成Java掌握的旅程! 在这里查看 !
目录
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提供了开发人员可能依赖的某些初始化保证。 未初始化的实例和类(静态)变量将自动初始化为其默认值。
让我们确认使用以下类作为简单示例:
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可见性规则,并且可以具有访问控制修饰符,该修饰符确定其他类是否可以调用特定的构造函数。
垃圾收集
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 {
@Override
public Book newBook() {
return new PaperBook();
}
}
public class KindleLibrary implements BookFactory {
@Override
public 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创建和销毁对象