十六、设计模式
设计模式(design pattern):是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。毫无疑问于,设计模式于己于他人于系统都是多赢的;设计模式使代码编制真正工程化;设计模式使软件工程的基石脉络,如同大厦的结构一样举足轻重。
单例设计模式(singleton):最常用、最简单的设计模式单例的编写有N中写法。
目的:保证一个在整个应用中某一个类有且只有一个实例(一个类在堆内存中只有一个对象),即所有指向该类型的实例的引用都指向同一块内存空间。
写单例设计模式的步骤
1.必须在该类中,自己先创建出一个对象;
2.私有化自身的构造器,防止外界通过构造器创建新的对象;
3.向外界暴露一个公共的静态方法,用于获取自身的对象。
如下代码:
class ArrayUtil{
private static final ArrayUtil instance = new ArrayUtil();
private ArrayUtil(){};
public static ArrayUtil getInstance(){
return instance;
}
}
public class SingletonDemo {
public static void main(String[] args) {
System.out.println(ArrayUtil.getInstance() == ArrayUtil.getInstance());//true
}
}
十七、工具类的设计
工具类:存放了某一类事物的工具方法的类
工具类存放的包:工具包(util,utils,tools/tool,helper/helpers),存放工具类
工具类起名:XxxUtil/XxxUtils/XxxTool等
比如ArrayUtil,StringUtil,JdbcUtil等
工具类如何设计:工具类在开发中其实只要存在一份即可。
1.如果工具类方法没有使用static修饰,说明工具方法需要使用工具类的对象来调用,此时把工具类设计成单例的;
2.如果工具方法全部使用static修饰,说明工具方法只需要使用工具类类名调用,此时必须将工具类构造器私有化。
一般情况下,首选第二种,在JDK中提供的工具类都是第二种,如java.util.Arrays类。
十八、基本类型的包装类
基本类型缺少对象,如果需要有对象,必须先有类。此时我们可以为每一个基本类型都编写一个对应的包装类,该类中包含了该基本类型的一个值。如 int 类型的一个包装类:
class IntWapper{
private int value;
public IntWapper(int value){
this.value = value;
}
}
public class WapperDemo {
public static void main(String[] args) {
IntWapper wapperr = null; //对象中无值
IntWapper wapper = new IntWapper(0);//对象中有值,但是值为0
}
}
基本数据类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
char | character |
double | Double |
boolean | Boolean |
八大基本数据类型都是最终类,不能被继承
装箱和拆箱操作:
装箱操作:把一个基本数据类型的值,转化为对应包装类的对象。
Integer num1 = new Integer(18);
Integer num1 = Integer.valueOf(18);
拆箱操作:把包装类的对象,转换为对应的基本类型变量。
int num3 = num1.intValue();
System.out.println(num1);//18 Integer类中已经重写了Object类中toString方法...
System.out.println(num2);//18
System.out.println(num3);//18
在Java集合框架中,只能储存对象,不能储存基本类型值
Sun公司在Java5开始提供自动装箱和自动拆箱操作:
自动装箱:可把一个基本类型变量直接赋给对应的包装类对象
Integer num4 = 18;
自动拆箱:可以把包装类的对象直接赋给对应的基本类型变量
Integer num5 = num4;
但是自动装箱和自拆箱在底层依然是手动装箱和手动拆箱,但是装箱用的是Integer.valueOf的方式,而不是new Integer
switch语句支持基本数据类型以及相对应的包装类对象,因为在底层,switch完成了自动装箱。
解释:Object obj = 18
1.自动装箱:Integer i = 18;
2.引用类型的自动类型转化,把子类对象赋给父类对象:Object obj = i;
Object可以接受一切数据类型
例如Object数组:
Object[] arr = {"ABC",12,3.14,false};
包装类的常用操作方法:
1.包装类的常量:
MAX_VALUE ,MIN_VALUE,SIZE(在内存中所占的位数),TYPE(基本类型的类型)
2.包装类的构造器, Xxx(xxx value),如Integer(Integer val)
构造器的作用:创建包装类对象;
3.基本类型和包装类型的转化(装箱和拆箱)
数类型具有以下几种方法:
Number类(数类型) |
---|
byteValue() |
shortValue() |
intValue() |
longValue() |
floatValue |
doubleValue |
4.String和基本类型/包装类的转换操作
将String转换为包装类类型:
方式一:
Integer i1 = Integer.valueOf("2018");
方式二:
Integer i2 = new Integer("2018");
把包装类对象转化为String类型:
String str = 对象.toString();
把基本数据类型转化为String:
int num = 2018;
String str = String.valueOf(num);
将String转换为基本数据类型:
String str = "2018";
int num = Integer.parseInt(str);
5.Boolean bool = new Boolean(“SB”);//false
底层只认可true/TRUE,其他均为false
十九、获取私有字段和私有方法
public class Person {
private int age = 5;
private String name;
private Person(){}
private String test(String name){
System.out.println("name: "+name);
return "test";
}
}
public class Test {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
// 1. 获取class对象
Class clazz = Person.class;
// 2. 获取私有无参构造
Constructor c = clazz.getDeclaredConstructor();
// 3. 设置访问为可见
c.setAccessible(true);
// 4. 通过构造器创建实例对象
Person person = (Person) c.newInstance();
// 根据字段名称获取class中的字段
Field age = clazz.getDeclaredField("age");
age.setAccessible(true);
System.out.println(age.getName() + " = " + age.get(person));
// 修改私有变量的默认值
age.set(person, 18);
System.out.println(age.getName() + " = " + age.get(person));
// 5. 获取所有字段
Field[] fields = clazz.getDeclaredFields();
for (Field f : fields) {
// 设置字段的可见性
f.setAccessible(true);
String name = f.getName();
Object o = f.get(person);
System.out.println(name + " - " + o);
}
// 6. 获取所有的方法
Method[] methods = clazz.getDeclaredMethods();
for (Method m : methods) {
m.setAccessible(true);
String name = m.getName();
Object invoke = m.invoke(person, "张三");
System.out.println(name + " = "+invoke);
}
}
}