Effective-JAVA 第一部分

本文深入探讨了Java中对象的创建、销毁与优化策略,强调了静态工厂方法、建造者模式、单例模式的重要性,以及如何避免不必要的对象创建,提高程序效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Effective-JAVA

2. CREATING AND DESTROYING OBJECTS创建和销毁对象

1. Use STATIC FACTORY METHODS instead of constructors 用静态工厂方法代替构造函数

ADVANTAGES 优势

  • Unlike constructors, they have names 不同于构造函数,他们有名字
  • Unlike constructors, they are not requires to create a new object each time they’re invoked 与构造函数不同,他们不需要在每次调用时创建一个新的对象
  • Unlike constructors, they can return an object of any subtype of their return type 不同于构造函数,他们可以返回一个原返回类型的子类型的对象
  • They reduce verbosity of creating parameterized type instances 他们减少创建参数化类型实例的冗长

DISADVANTAGES 劣势

  • If providing only static factory methods, classes without public or protected constructors cannot be subclassed (encourage to use composition instead inheritance). 如果只提供静态工厂方法,没有公共的或受保护的类构造函数不能从它派生出子类(鼓励使用组合而不是继承)。
  • They are not readily distinguishable from other static methods (Some common names (each with a different pourpose) are: valueOf, of, getInstance, newInstance, getType and newType) 他们不容易区分从其他静态方法(一些常见的名字(pourpose各异):返回对象的值,,getInstance,newInstance,方法和newType)
public static Boolean valueOf(boolean b){
		return b ? Boolean.TRUE :  Boolean.FALSE;
	}

2. Use BUILDERS when faced with many constructors 当面对许多构造函数时用建设者

Is a good choice when designing classes whose constructors or static factories would have more than a handful of parameters. 是一个很好的选择在设计类的构造函数或静态工厂会有多少量的参数

Builder pattern simulates named optional parameters as in ADA and Python. 建造者模式模拟命名可选参数如ADA和Python。

public class NutritionFacts {
		private final int servingSize;
		private final int servings;
		private final int calories;
		private final int fat;
		private final int sodium;
		private final int carbohydrate;

		public static class Builder {
			//Required parameters
			private final int servingSize:
			private final int servings;

			//Optional parameters - initialized to default values
			private int calories		= 0;
			private int fat 			= 0;
			private int carbohydrate 	= 0;
			private int sodium 			= 0;

			public Builder (int servingSize, int servings) {
				this.servingSize = servingSize;
				this.servings = servings;
			}

			public Builder calories (int val) {
				calories = val;
				return this;				
			}

			public Builder fat (int val) {
				fat = val;
				return this;				
			}

			public Builder carbohydrate (int val) {
				carbohydrate = val;
				return this;				
			}

			public Builder sodium (int val) {
				sodium = val;
				return this;				
			}

			public NutritionFacts build(){
				return new NutritionFacts(this);
			}
		}

		private NutritionFacts(Builder builder){
			servingSize		= builder.servingSize;
			servings 		= builder.servings;
			calories		= builder.calories;
			fat 			= builder.fat;
			sodium 			= builder.sodium;
			carbohydrate		= builder.carbohydrate;
		}
	}

Calling the builder

NutritionFacts cocaCola = new NutritionFacts.Builder(240,8).calories(100).sodium(35).carbohydrate(27).build();

3. Enforce the singleton property with a private constructor or an enum type 执行单属性与一个私有构造函数或枚举类型

There are different ways to create singletons: 有不同的方法来创建单例:

Public final field 静态字段

public class Elvis{
		public static final Elvis INSTANCE = new Elvis();
		private Elvis(){...}
		...
		public void singASong(){...}
	}

One problem is that a privileged client can invoke the private constructor reflectively. Against this attack the constructor needs to be modified to send an exception if it is asked to create a second instance. 一个问题是,有特权的客户机可以反射调用私有构造函数。针对这种攻击,如果要求创建第二个实例构造函数需要发送修改异常。

**Singleton with static factory ** 单例模式与静态工厂

public class Elvis{
		private static final Elvis INSTANCE = new Elvis();
		private Elvis(){...}
		public static Elvis getInstance(){ return INSTANCE; }
		...
		public void singASong(){...}
	}

In this approach it can be change to a non singleton class without changing the class API. 在这种方法中它可以改变一个非单例类不改变类的API。

**Serialize a singleton ** 序列化一个单例

It is needed a readResolve method and declare all the fields transient in addition to the implements Serializable to maintain the singleton guarantee. 需要一个readResolve方法并宣布所有字段瞬态除了实现了Serializable保持独立的保证。

private Object readResolve(){
		//Return the one true Elvis and let the garbage collector take care of the Elvis impersonator
		return INSTANCE;
	}

Enum Singleton, the preferred approach (JAVA 1.5) Enum Singleton,首选的方法(JAVA 1.5)

public enum Elvis(){
		INSTANCE;
		...
		public void singASong(){...}
	}

Equivalent to the public field, more concise, provides serialization machinery for free, and guarantee against multiple instantiation, even for reflection attacks and sophisticated serialization. It is the best way to implement a singleton. 相当于公共领域,更简洁,免费提供序列化机械,并保证对多个实例化,即使对于反射攻击和复杂的序列化。这是最好的方法来实现一个单例。

4. Enforce noninstantiability with a private constructor 执行noninstantiability私有构造函数

For classes that group static methods and static fields. 类的静态方法和静态字段。

Used for example to: 例如:使用

  • Group related methods on primitive values or arrays. 组织相关的原始值或数组的方法。
  • Group static methods, including factory methods, for objects that implement a particular interface. 静态方法,包括工厂方法,实现特定接口的对象。
  • Group methods on a final class instead of extending the class. 组最后一个类,而不是扩展类上的方法。

Include a private constructor

	public class UtilityClass{
		// Suppress default constructor for noninstantiability
		// (Add comment to clarify why the constructor is expressly provided)
		private UtilityClass(){
			throw new AssertionError();
		}
		...
	}

5. Avoid creating objects 避免创建对象

REUSE IMMUTABLE OBJECTS 重复使用使用不变的对象

Don’t do this 不要这样做

	String s = new String("stringette");		

Every call creates a new String instance. The argument “stringette” is itself one. This call in a loop would create many of them. 每个调用创建一个新的字符串实例。参数“stringette”本身就是一个。这个调用在一个循环中会创造很多。

Do this 这样做

	String s = "stringette";		

This one uses a single String instance rather than creating a new one. 这一次使用一个字符串实例而不是创建一个新的。

**Use static factory methods in preference to constructors [ Item 1](# 1. Use STATIC FACTORY METHODS instead of constructors 用静态工厂方法代替构造函数)**使用静态工厂方法优先于构造函数项1`

Boolean.valueOf(String); Is preferable to the constructor Boolean(String).

REUSE MUTABLE OBJECTS THAT WON’T BE MODIFIED 重用可变的对象不会被修改

Don’t do this

	public class Person {
	private final Date birthDate;
	...
		public boolean isBabyBoomer(){
			// Unnecessary allocation of expensive object.
			Calendar gmtCal= Calendar.getInstance(TimeZone.getTimeZone("GMT"));
			gmtCal.set(1946,Calendar.JANUARY,1,0,0,0);
			Date boomStart = gmtCal.getTime();
			gmtCal.set(1965,Calendar.JANUARY,1,0,0,0);
			Date boomEnd = gmtCal.getTime();
			return birthDate.compareTo(boomStart) >= 0 &&birthDate.compareTo(boomEnd)<0;
		}
	}

isBabyBoomer creates a new Calendar,TimeZone and two Date instances each time is invoked. isBabyBoomer创建一个新的日历,时区和两个日期每次调用实例。

	public class Person {
	private final Date birthDate;
	...
	private static final Date BOOM_START;
	private static final Date BOOM_END;

	static {
			Calendar gmtCal= Calendar.getInstance(TimeZone.getTimeZone("GMT"));
			gmtCal.set(1946,Calendar.JANUARY,1,0,0,0);
			BOOM_START = gmtCal.getTime();
			gmtCal.set(1965,Calendar.JANUARY,1,0,0,0);
			BOOM_END = gmtCal.getTime();
	}
		public boolean isBabyBoomer(){
			return birthDate.compareTo(BOOM_START) >= 0 &&birthDate.compareTo(BOOM_END)<0;
		}
	}

**Prefer primitives to boxed primitives, and watch out for unintentional autoboxing ** 喜欢原语盒装原语,提防意外自动装箱

	//Slow program. Where is the object creation?
	public static void main (String[] args){
		Long sum = 0L;
		for (long i = 0 ; i<= Integer.MAX_VALUE; i++){
			sum+=i;
		}
		System.out.println(sum);
	}

sum is declared as Long instead of long that means that the programs constructs
Long instances.

**Object pools are normally bad ideas ** 对象池通常坏主意

Unless objects in the pool are extremely heavyweight, like a database connections. 除非对象池中非常重量级的,像一个数据库连接。

英文版 https://github.com/HugoMatilla/Effective-JAVA-Summary

### 回答1: 《Effective Java第三版》是由Joshua Bloch所著的一本Java编程指南。这本书是基于第二版的更新版本,目的是给Java程序员提供一些最佳实践和经验,以编写高效、可维护和可靠的Java代码。 这本书共分为15个章节,每个章节都讲解了一个与Java开发有关的重要主题。比如,章节一讲述了使用静态工厂方法代替构造器的优点,章节二则介绍了如何用Builder模式来构建复杂的对象。此外,书中还提及了Java对象的等价性、覆盖equals方法和hashCode方法、避免创建不必要的对象、使用泛型、枚举、lambda表达式等等。 《Effective Java第三版》通过具体的代码示例和清晰的解释来说明每个主题的关键概念,使读者能够更好地理解和应用。此外,书中还提供了一些实用的技巧和技术,例如避免使用原始类型、尽量使用接口而非类来定义类型等。 总的来说,这本书提供了很多实用的建议和技巧,可以帮助Java开发者写出高质量的代码。无论是初学者还是有经验的开发者,都可以从中受益匪浅。无论你是打算从头开始学习Java编程,还是已经有一定经验的开发者,这本书都是值得推荐的读物。 ### 回答2: 《Effective Java 第三版》是由Joshua Bloch 所著的一本Java编程指南,是Java程序员必读的经典之作。该书共包含90个条目,涵盖了各种Java编程的最佳实践和常见问题的解决方法。 本书分为多个部分,每个部分都侧重于一个特定的主题。作者探讨了Java编程中的各种问题和挑战,并提供了解决方案和建议。这些建议包括如何选择和使用合适的数据结构和算法,如何设计高效的类和接口,如何处理异常和错误,以及如何编写可读性强的代码等等。 《Effective Java 第三版》还关注了Java编程中的性能优化和安全性问题。作者强调了遵循Java语言规范、使用标准库、防范常见安全漏洞等重要原则。此外,本书还介绍了Java 8及其后续版本的新特性和用法,如Lambda表达式、流式编程和Optional类等。 这本书的特点之一是每个条目都独立于其他条目,可以单独阅读和理解。每个条目开头都有一个简洁的总结,让读者能够快速掌握主要观点。此外,书中还有大量的示例代码和解释,帮助读者更好地理解和运用所学知识。 总的来说,《Effective Java 第三版》是一本非常实用和全面的Java编程指南。它适用于各个层次的Java程序员,无论是初学者还是有经验的开发人员,都可以从中获得宝贵的经验和知识。无论是编写高质量的代码、优化性能还是确保安全性,这本书都是一本不可或缺的参考书籍。 ### 回答3: 《Effective Java 第3版(中文版)》是由 Joshua Bloch 所著的一本关于使用 Java 编程语言的指南书。该书是对 Java 语言的最佳实践的详尽描述,为中高级 Java 开发人员提供了许多实用的建议和技巧。 该书的主要内容包括Java 语言的优雅编程风格、类和接口的设计、Lambda 表达式和流的使用、泛型、异常和并发编程等方面的最佳实践。 在《Effective Java 第3版(中文版)》中,许多传统的 Java 开发中的陷阱、常见错误和不良习惯都得到了深入的剖析和解答。它不仅提供了可供开发人员参考的示例代码,还解释了为什么某种方式是有问题的,以及如何更好地进行改进。 该书的深度和广度非常适合正在努力提高 Java 编程技能的开发人员。它涵盖了多个关键领域,为读者提供了在实际项目中解决常见问题的方法和思路。 此外,《Effective Java 第3版(中文版)》还介绍了最新版本的一些特性和改进。例如,它详细说明了如何正确地使用 Java 8 中新增的 Lambda 表达式和流,以及如何充分利用 Java 9、10 和 11 中的新功能。 总之,这本书是 Java 开发人员必备的指南之一。通过深入理解和应用书中的实践建议,读者可以更加高效地编写、优化和维护 Java 代码。无论是想提升职业技能还是在项目中减少错误和问题,这本《Effective Java 第3版(中文版)》都是一本非常有帮助的参考书。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值