工具类(utility class)不希望被实例化,比如只包含静态方法和静态域的类.为了这个目的,需要让这个类包含一个私有构造器. // 私有构造器示例 public class UtilityClass { // 为该类不能被实例化.子类化添上注释 private UtilityClass() { // 避免不小心在类的内部调用构造器 throw new AssertionError(); } } 其他不可行方法和理由: 1. 将类写成抽象类:可被子类化,甚至误导用户子去继承这个类. 2. 不…
只有当类不包含显式的构造器时,编译器才会生成一个公有的.无参的缺省构造器.只要让一个类包含私有构造器,这个类就不能被实例化了.示例: // 工具类 public class UtilityClass { // 私有构造器 private UtilityClass { throw new AssertionError(); } // 其他操作... } AssertionError避免在类的内部调用构造器,保证该类在任何情况下都不会被实例化.同时,这个类不能被子类化,因为子类构造器无法显式或隐式地…
通过私有构造器强化不可实例化的能力 原理:只有当类不包含显式的构造器时,编译器才会生成缺省的构造器,因此只要让这个类包含私有构造器,他就不能被实例化 这种方式下,子类没有可访问的超类构造器可调用 //只有当类不包含显式的构造器时,编译器才会生成缺省的构造器,因此只要让这个类包含私有构造器,他就不能被实例化 // private StrongSingletonByConstr{ // throw new AssertionError();//非必需..>>避免在类的内部调用构造器 // }…
场景: 在创建工具类的时候,大部分是无需实例化的,实例化对它们没有意义.在这种情况下,创建的类,要确保它是不可以实例化的.   存在问题: 在创建不可实例化的类时,虽然没有定义构造器.但是,客户端在使用该类的时候,依然可以实例化它.客户端,可以继承该类,通过实例化其子类来实现实例化:客户端可以调用默认的构造器来实例化该类.   要避免这个问题,使用的方式是,定义一个私有的构造器: public class UtilityClass { // Suppress default constructo…
  第 1 条:用静态工厂方法代替构造器 对于类而言,获取一个实例的方法,传统是提供一个共有的构造器. 类可以提供一个公有静态工厂方法(static factory method), 它只是一个返回类的实例的静态方法. 示例:Boolean的装箱类,将boolean基本类型值转换成一个Boolean对象引用 public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; } 静态工厂方法与构造…
实现Singleton(代表本质上唯一的系统组件)的三种方法: 1. 保持私有构造器,导出公有的静态成员,客户端访问该类的唯一实例. 2. 保持私有构造器,公有的成员是静态工厂方法. 3. 单元素的枚举类型已经成为实现Singleton的最佳方法. 前两种方法有两点注意: 1. 享有特权的客户端可以通过反射机制调用私有构造器.如果需要抵御这种攻击,可以修改构造器,让它在被要求创建第二个实例的时候抛出异常. 2. 如果要使其变成可序列化的,需要: (1) implement Serializabl…
Singleton指仅仅被实例化一次的类.Singleton通常被用来代表那些本质上唯一的系统组件,比如窗口管理器或者文件系统.使类成为Singleton会使它的客户端测试变得十分困难,因为无法给Singleton替换模拟实现,除非它实现一个充当其类型的接口. 在Java 1.5发行版本之前,实现Singleton有两种方法. 第一种方法,公有静态成员是个final域: public class Elvis { public static final Elvis INSTANCE = new E…
Singleton指仅仅被实例化一次的类,通常用来代表那些本质上唯一的系统组件,实现Singleton有三种方法: 1)公有静态成员是个final域,享有特权的用户可以调用AccessibleObject.setAccessible方法,通过反射机制调用私有构造器. public class User{ public static final User INSTANCE = new User(); private User{ } public void doSomeThing(){...} }…
类有多个可选参数的解决方案: 1. 重叠构造器模式可行,但是当有许多参数的时候,客户端代码会很难编写,并且仍然较难以阅读. 2. JavaBeans模式,调用一个无参构造器来创造对象,然后调用setter方法来设置每个必要的参数,以及每个相关的可选参数. 缺点:构造过程被分到了几个调用中,在构造过程中JavaBean可能处于不一致的状态.阻止了把类做成不可变的可能,需要程序员确保线程安全. 3. Builder模式,模拟了具名的可选参数. 模式 优 劣 重叠构造器 写法最简单 多参数时候难读.难…
获取类的实例有两种方法: 1. 提供一个公有的构造器(最常用). 2. 提供一个公有的静态工厂方法(static factory method). // 静态工厂方法示例 public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; } 静态工厂方法的优势: 1. 有名称.当一个类需要多个带有相同签名(方法签名 = 方法名 + 参数列表)的构造器时,就用静态工厂方法代替构造器,并且慎重选择名…
在许多时候,我们会写一个类,这个类只是用来提供一些静态方法或静态属性,就好像C++的函数一样,比如 java.lang.Math,java.util.Arrays等,但是有时候这些类的用户可能会在无意思的情况下是构造函数生成一个这个类的对象,但是这个对象没有任何意义. 这样实例类(utility classes)原本不使用来实例化的,但是编译器会在没有显示提供构造函数的情况下提供一个公共的,无参的构造函数.为了避免这种情况,我们可以直接包含一个私有的构造方法来防止这种类的实例化: public…
第 15 条: 使类和成员的可访问性最小化 软件设计基本原则:信息隐藏和封装. 信息隐藏可以有效解耦,使组件可以独立地开发.测试.优化.使用和修改.   经验法则:尽可能地使每个类或者成员不被外界访问. 对于成员(属性.方法.嵌套类和嵌套接口),有四种可能的访问级别,在这里,按照可访问性从小到大列出: private —— 该成员只能在声明它的顶层类内访问. default (package-private) —— 成员可以从被声明的包中的任何类中访问.从技术上讲,如果没有指定访问修饰符(接口成…
第 10 条:覆盖equals时请遵守通用约定 在不覆盖equals方法下,类的每个实例都只与它自身相等. 类的每个实例本质上都是唯一的. 类不需要提供一个”逻辑相等(logical equality)”的测试功能. 父类已经重写了 equals 方法,并且父类的行为完全适合于该子类. 类是私有的或包级私有的,并且可以确定它的 equals 方法永远不会被调用. 什么时候需要覆盖equals方法?  如果一个类包含一个逻辑相等( logical equality)的概念——此概念有别于对象同一性…
1. 如果对象是不可变的(immutable),它就始终可以被重用. (1) 特别是String类型的对象. String str1 = new String("str"); // 创建许多不必要的实例 String str2 = "str"; // "str"其本身是一个String实例,对于所有同一台虚拟机中运行的代码,只要它们包含相同的字符串字面常量,该对象就会被重用 (2) 同时提供了静态工厂方法和构造器的不可变类,通常可以使用静态工厂方…
第 26 条:请不要使用原生态类型 声明中具有一个或多个类型参数的类或者接口,就是泛型(generic). 例如List接口只有单个类型参数E, 表示列表的元素类型.这个接口全称List<E>,泛型类和接口统称为泛型(generic type). 每一种泛型都定义一个原生态类型(raw type),即不带任何实际类型参数的泛型名称. 它的存在主要是为了兼容泛型之前的代码.   如果使用原生态类型,就失去了泛型在安全性和描述性方面的优势. 如果使用像List这样的原生态类型,就会失掉类型安全性,…
在Java 8中,添加了函数式接口(functional interface),Lambda表达式和方法引用(method reference),使得创建函数对象(function object)变得更加容易.还有 Stream API为处理数据元素序列提供类库级别的支持. 第42条:Lambda匿名类 以前,用带有单个抽象方法的接口作为函数类型(function type),它们的实例称为函数对象(function object),表示函数或者要采取的动作.JDK1.1开始,创建函数对象的主要…
Java支持两种引用类型的特殊用途的系列:一种称为枚举类型(enum type)的类和一种称为注解类型(annotation type)的接口. 第34条:用enum代替int常量 枚举是其合法值由一组固定的常量组成的一种类型,例如一年中的季节,太阳系中的行星. 在将枚举类型添加到该语言之前,表示枚举类型的常见模式是声明一组名为int的常量,每个类型的成员都有一个常量. int枚举模式的技术有许多缺点.不具有类型安全性,也没有描述性可言. Java提供了一种避免int和String枚举模式的所有…
Singleton指只被实例化一次的类.一般用来搞那些创建很耗资源或者要求系统中只能有一个实例的类. 这个很经常使用.记得曾经实习面试的时候就有这个面试题. 一般採用的方法是将构造器私有化,然后提供一个static变量,再提供一个static的public方法用来返回static实例: //Singleton with static factory public class Elvis { private static final Elvis INSTANCE = new Elvis(); pr…
1.单例类到现在为止算是比较熟悉的一种设计模式了,最开始写单例模式是在C#里面,想要自己实现一个单例类,代码如下: public class Instance { private static readonly Instance instance = new Instance(); public static Instance Instance { get { return instance; } } private Instance() { } } 嗯,这是一贯的写法. <Effective…
前言 该读书笔记用于记录在学习<深入理解Java虚拟机--JVM高级特性与最佳实践>一书中的一些重要知识点,对其中的部分内容进行归纳,主要是方便之后进行复习. 运行时数据区域 Java虚拟机在执行过程中会将其管理的内存划分为多个不同的数据区域.其中一些区域随着虚拟机启动而创建,一些区域生命周期则依赖用户线程的启动和结束. 下面是JDK1.7 程序计数器 是一块较小的内存空间,用于记录当前线程所执行的字节码的行号,在执行过程中通过改变计数器的值来选择下一条被执行的指令.分支.循环.异常处理等都通…
永远在使用对象之前先将它初始化.对于无任何成员的内置类型,你必须手工完成此事. 至于内置类型以外的任何其他东西,初始化责任落在构造函数身上.规则很简单:确保每一个构造函数都将对象的每一个成员初始化. 构造函数成员初始化列表: 这里有一个规则:总是在初始化列表中列出所有成员变量,即使有的成员变量是内置类型(内置类型的初始化和赋值成本相同). 成员初始化顺序 base classes 早于 derived classes 被初始化,class 的成员变量总是以其声明次序被初始化 一个编译单元内定义的…
学完java有一段时间了,一直没有做对应的总结,总认为有一种缺憾.从这篇博客開始,将自己平时的学习笔记进行总结归纳,分享给大家. 这篇博客主要简单的介绍一下java的基础知识,基本的目的是扫盲.原来仅仅是听说过java,如今自己真正開始学习了,看完了第一集视频之后,问自己,你知道java是什么吗?问完之后才发现一无所知,上完查一查,简单了解一下,给自己扫盲. 介绍 知道java是一种可跨平台应用软件的面向对象的程序设计语言,就能够了. 组成 Java由四方面组成:java编程语言,java类文件…
1.定时器Timer类 构造定时器时,需要设置一个时间间隔,并告知定时器,当到达时间间隔时需要做什么操作.定时器需要知道调用哪一个方法,并要求传递的对象所属的类实现了java.awt.event包的ActionListener接口 例: Class TimePrinter implements ActionListener { public void actionPerformed(ActionEvent event ) { Date now = new Date(); System.out.p…
前言 最近开始看这本书,记得前段时间拿起这本书的时候,心情是相当沉重的!当时的剧本是这样的-- 内景.家里 - 下午 我(画外):唉,有点无聊啊!(偶然撇过书架)这么多书得看到什么时候啊,要不要拿一本翻翻呢?但是在家里好像有点看不下去啊,是太安逸了吗?最近那本<图解 HTTP>也还没看完,感觉暂时有点不想看了.(走到书架前)还是挑几本优先级比较高的带到███下班的时候看吧.(沉思)嗯,这本带过去~ 当我拿起<深入理解 Java 虚拟机>这本书的那一刻,心里咯噔一下--唉,PM10…
1.让自己习惯C++ 条款01:视C++为一个语言联邦 C++高效编程守则视状况而变化,取决于你使用C++的哪一部分. 条款02:尽量以const.enum.inline替换 #define 对于单纯常量,最好以const对象或enum替换#define 对于形似函数的宏,最好改用inline函数替换#define 条款03:尽可能使用const 将某些东西声明为const可帮助编译器侦测出错误用法.const可被施加于任何作用域内的对象.函数参数.函数返回类型.成员函数本体. 编译器强制实施b…
下了这本书<Java多线程编程指南-设计模式篇>, 还有另一本<JAVA多线程设计模式>,据说内容有重复,结合着看.…
java中主要的同步机制是关键字synchronized,它提供一种独占锁,但是 同步这个术语还包括validate类型的变量,显示锁(Explicit Lock)以及原子变量. -------显示锁,不明白这个具体指什么? 线程安全: 当多个线程访问某一个类时,这个类始终都能表现出正确的行为,那么就可以称为这个类是线程安全的. java提供了一种内置的锁机制来支持原子性:同步代码块(synchronized Block),同步代码块包括两部分,一个作为锁对象引用,一个作为由这个锁保护的代码块.…
1.1 数组初始化 1.1.1 java数组是静态的 java数组被初始化之后,该数组所占的内存空间.数组长度都是不可变的. java程序中的数组必须经过初始化才可使用. 数组的初始化有两种方式: 1) 静态初始化:初始化时由程序员显示指定每个数组元素的初始值,由系统决定数组长度. 2) 动态初始化:初始化时程序员只指定数组长度,由系统为数组元素分配初始值. *不要同时使用静态初始化和动态初始化方式. java的数组变量是一种引用类型的变量,数组变量并不是数组本身,它只是指向对内存中的数组对象.…
这个条目叫做,尽量使用编译器而不要使用预处理器更好.#define并没有当作语言本身的一部分. 例如下面的例子: #define ASPECT_RATIO 1.653 符号名称永远不会被编译器看到.它可能在源码到达编译器之前被预处理器移除.ASPECT_RATIO 最终不会进入符号表,如果因为这个常量的使用而导致编译错误,会使你非常迷惑,因为错误信息会指向1.653而不是ASPECT_RATIO.如果ASPECT_RATIO被定义在一个不是你自己写的头文件中,你会不知道1.,653来自哪里.,…
问题描述-阻止对象的拷贝 现实生活中的房产中介卖房子,一个服务于这个中介的软件系统很自然的会有一个表示要被销售的房屋的类: class HomeForSale { ... }; 每个房产中介会立刻指出来,要销售房屋的每个属性都是唯一的,没有两个完全一样的房屋.在这种情况下,拷贝一个HomeForSale对象就没有任何意义了.你在怎么能拷贝一些独一无二的东西呢?因此你可能会尝试,如果有拷贝HomeForSale对象的函数,代码将不能够通过编译. HomeForSale h1; HomeForSal…