文档章节

《Effective java》学习笔记 1 之 对象创建和销毁

厚德
 厚德
发布于 2015/06/10 15:33
字数 1229
阅读 14
收藏 0
点赞 0
评论 0

        最近看知乎上Android成长之路的帖子推荐了一本书《Effective java》于是下了个中文版的pdf开始学习,鉴于自己英文太差阅读英文版太吃力,所以下了中文版。

    1.使用静态工厂方法来代替构造器(此处静态工厂方法和设计模式的工厂方法不同)

        优点:

1 它有名称,可以更加确切的描述创建的对象。例如BigInteger(int,int,Random)可以使用 BigInteger.probablePrime(int,Random)代替 

2 不必每次都调用他们的时候都创建一个新的对象

3 可以返回原返回类型的任何子类型的对象

4 在创建参数化类型实例的时候,它们使代码变得更加简洁

缺点:

1 如果不含共有的或者受保护的构造器,就不能被子类化。

2 它们于其他的静态方法实际上没有任何区别。

2.遇到了多个构造器参数时要考虑使用构造器

    1 使用重叠构造器

缺点:当参数有许多的时候,客户端代码会很难写,并且难以阅读。

2 使用javaBeans的模式,通过setter方式来设置参数

缺点:构造过程中被分到几个调用中,在构造过程中javaBean可能处于不一致的状态。不安全

3 使用Builder模式

package com.effetive.creation;

import java.util.WeakHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;

/**
 * 营养成分
 * 
 * @author Administrator
 * 
 */
public class NutritionFast {
	// 必选参数
	private int servingSize;
	private int servings;
	// 可选参数
	private int calories;
	private int fat;
	private int sodium;
	private int catbohydrate;
		
	private NutritionFast(Builder builder) {
		servingSize = builder.servingSize;
		servings = builder.servings;
		calories = builder.calories;
		fat = builder.fat;
		sodium = builder.sodium;
		catbohydrate = builder.catbohydrate;
	}

	public static class Builder {
		// 必选参数
		private int servingSize;
		private int servings;
		// 可选参数
		private int calories;
		private int fat;
		private int sodium;
		private int catbohydrate;

		public Builder(int servingSize, int servings) {
			super();
			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 sodium(int val) {
			sodium = val;
			return this;
		}

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

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

	public static void main(String[] args) {
		// 调用
		NutritionFast cocaCola = new NutritionFast.Builder(240, 8)
				.calories(100).sodium(35).build();

	}
}

如果构造器中或静态工厂中具有多个参数,可以选择Builder模式,如果参数比较少还是选择重叠的方式。

3.用私有的构造器或者枚举强化singleton属性(个人感觉使用枚举来做单例模式,我好像没见过)

        public class Elvis{
		private static final Elvis instance = new Elvis();
		private Elvis(){}
		public static Elvis getInstance(){
			return instance;
		} 
		public void leavTheBuilding(){}
	}
	
	public enum Elvis{
		INSTANCE;
		public void leavTheBuilding(){}
	}

4.避免创建不必要的对象

String s = new String("abcd");

String s = "abcd";

我们选择第二种方式,因为第一中方式会创建出2个对象。

Long sum =0l;

for(long i =0; i<Integer.MAX_VALUE;i++){

sum +=i;

}

如果我们把Long 改为long 可以少创建出2^31个Long对象。所以尽量使用基本数据类型。

5.消除过期的对象引用

//自己维护一个栈
	public class Stack{
		private Object[] elements;
		private int size = 0;
		private static final int DEFAULT_INITIAL_CAPACITY = 16; //初始的容量
		
		public Stack(){
			elements = new Object(DEFAULT_INITIAL_CAPACITY);
		}
		
		public void push(Object e){
			ensureCapacity();
			elements[size++] = e;
		}
	
		public Object pop(Object e){
			if(size==0){
				throw new EmptyStackException();
			}
			Object result = elements[--size];
			//elements[--size] = null;
			return result;
		}
		
		//如果容量不够进行扩充
		public void ensureCapacity(){
			if(elements.length == size){
				elements = Array.copy(elements,2*size+1);
			}
		}
	}

这段程序运行起来可能没有什么错误,但是确存在这严重的内存泄露,如果对Stack的进行压栈操作,然后再进行弹栈,但是弹栈的对象是不能被垃圾回收站回收,因为是个强引用(还在elements数组中)。如果这种过期的引用对象(obsolete reference)没有被回收,可能会出现OutOfMemory的情况.修改方式 :就是把弹栈的对象给制空。

引用过期对象容易出现位置:

1 自己管理的Stack 、存储池、数组 

解决方案:一旦容器元素变成非活动部分的一部分,我们就要手动清空这些容器元素

2 缓存 

一旦你把对象放在缓存中,它很容易被遗忘,从而使它在很长一段时间不使用的时候仍然保留在内存中。

解决方案:可以使用WeakHashMap来当做缓存容器;还可以使用使用Timer,ScheduledThreadPoolExecutor定时器来定时清理

3 内存泄漏还可能出现在监听器或其他回调中 ,可以使用WeakReference作为WeakhashMap的键

例如,在Android中有很多地方Context对象,我们很多时候会在Activity直接用this代表Context,如果这个Activity已经关闭就应该被垃圾回收器回收,但是我们的通过参数的来传递Activity对象,可能其他地方还引用着这个activity对象。我们解决方案可以用this.getApplicationContext()这样可以避免了Activity内存泄漏

我可以使用工具来查找内存泄漏比如Heap Profiler

© 著作权归作者所有

共有 人打赏支持
厚德
粉丝 2
博文 53
码字总数 33193
作品 0
武汉
JVM 运行时数据区简介及堆与栈的区别

理解JVM运行时的数据区是Java编程中的进阶部分。我们在开发中都遇到过一个很头疼的问题就是OutOfMemoryError(内存溢出错误),但是如果我们了解JVM的内部实现和其运行时的数据区的工作机制,...

大数据之路
2015/08/02
0
1
effective java之创建与销毁对象

最近朋友推荐了一本书《Effective Java》,觉得写得不错,写点总结笔记,以备后用。 一、创建对象 1、考虑静态工厂代替构造器 优点:(1)有明确名称。可以理解成,定义的静态方法可以给出明...

kyle1970
2012/10/31
0
0
第三章 spring-bean之DefaultSingletonBeanRegistry(3)

前言 SingletonBeanRegistry是一个非常重要的接口,用于注册,获得,管理singleton对象。 SingletonBeanRegistry目前唯一的实现是DefaultSingletonBeanRegistry,DefaultSingletonBeanRegis...

鸟菜啊
昨天
0
0
Java入门学习之java变量简析 java编程

在Java语言中,所有的变量在使用前必须声明。声明变量的基本格式如下: type identifier [ = value][, identifier [= value] ...] ; Java语言支持的变量类型有3种:1、类变量:独立于方法之外...

老男孩Linux培训
05/29
0
0
Java 内存分配全面浅析

本文将由浅入深详细介绍Java内存分配的原理,以帮助新手更轻松的学习Java。这类文章网上有很多,但大多比较零碎。本文从认知过程角度出发,将带给读者一个系统的介绍。 进入正题前首先要知道...

vieky
2014/12/10
0
3
JVM学习之——Java内存区域

为了加深对Java语言的理解,加深对Java虚拟机工作机制、底层特性的了解和掌握,准备在闲暇时间,抽空对《深入理解Java虚拟机 JVM高级特性与最佳实践》一书进行学习。本文是学习此书第2章时的...

你想要怎样的未来
05/27
0
0
111 多线程JUC包下代码分析

Java多线程系列目录(共43篇) AtomicLongFieldUpdater:通过反射+CAS实现对传入对象的指定long字段实现类似AtomicLong的操作 http://www.cnblogs.com/skywang12345/p/javathreadscategory.ht...

素雷
2017/10/31
0
0
Java虚拟机运行时数据区结构

本文部分参考自《Java虚拟机规范(Java SE 7版)》的中译本和周志明的《深入理解Java虚拟机》,另加个人理解。原书对Java虚拟机运行时数据区描述只有6页,同时参考其他网络网资料,个人能力所...

foodon
2014/12/09
0
4
Java程序员应了解的10个面向对象设计原则

面向对象设计原则是 OOPS(Object-Oriented Programming System,面向对象的程序设计系统)编程的核心,但大多数 Java 程序员追逐像 Singleton、Decorator、Observer 这样的设计模式,而不重...

effort_fan
2012/04/09
0
0
正确理解ThreadLocal

首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。各个线程中...

Idiot_s_Sky
2014/01/04
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

全新内存布局Android5 for one x

众所周知Android5.0默认ART模式,运行速度加倍,软件占用内存也加倍,我们one x这种元老机采用旧的内存布局,data空间2g ART模式下安装几个软件也就不够用了。最近逛国外的xda论坛,发现有大...

CrazyManDF
9分钟前
0
0
web3j转账

 web3 转账功能   为了完成以太坊交易,必须有几个先决条件   1、对方的以太坊地址   2、确定要转账的金额   3、自己地址的转账权限   4、大于转账金额的以太币,以太币转账其实就...

智能合约
10分钟前
0
0
10.28 rsync工具介绍 , rsync常用选项, rsync通过ssh同步

rsync远程同步 重点!重点!!重点!!! 例子 • rsync -av /etc/passwd /tmp/1.txt • rsync -av /tmp/1.txt 192.168.188.128:/tmp/2.txt rsync格式 • rsync [OPTION] … SRC DEST • rs......

Linux_老吴
23分钟前
0
0
iis php 环境搭建,非常详细的教程

准备篇 一、环境说明: 操作系统:Windows Server 2016 PHP版本:php 7.1.0 MySQL版本:MySQL 5.7.17.0 二、相关软件下载: 1、PHP下载地址: http://windows.php.net/downloads/releases/ph...

T_star
25分钟前
0
0
Day35 rsync通过服务同步

rsync通过服务同步 rsyncd.conf配置文件详解 port:指定在哪个端口启动rsyncd服务,默认是873端口。 log file:指定日志文件。 pid file:指定pid文件,这个文件的作用涉及服务的启动、停止等...

杉下
31分钟前
1
0
【最新最全】为 iOS 和 Android 的真机和模拟器编译 Luajit 库

编译 Luajit 库,的确是一个挑战。因为官网的教程,在当前版本的 Xcode 和 NDK 环境中,已经不适用了。以前只是编译了适用于真机的 Luajit 库。最近在尝试编译模拟器 Luajit 库,就顺便梳理了...

ios122
31分钟前
0
0
rsync至ssh同步

rsync: 文件同步工具,可实现“增量拷贝”;使用yum安装rsync包 常用选项:-a=-rtplgoD (-r同步目录,-t保持文件的时间属性,-p保持文件的权限属性,-l保持软连接,-g保持文件的属组,-o保持...

ZHENG-JY
36分钟前
0
0
TradingView 学习笔记

#前言 公司最后需要使用TradingView展示K线图走势。由于之前没接触过,拿到文档时一脸蒙逼。还好找到二篇文章+Demo代码,直接改改就行了。 #被批 由于上面的懵懂,有个问题困扰4个小时没解决...

hihubs
37分钟前
0
0
10.28 rsync工具介绍~10.31 rsync通过ssh同步

rsync命令是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件。rsync使用所谓的“rsync算法”来使本地和远程两个主机之间的文件达到同步,这个算法只传送两个文件的不同部分,而...

洗香香
39分钟前
1
0
卷积为什么要旋转180度

参考《最容易理解的对卷积(convolution)的解释》 https://blog.csdn.net/bitcarmanlee/article/details/54729807 这篇博客详细讲解了“卷积”,提及了为什么要反转180度,我简述下。 1.卷积的...

datadev_sh
48分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部