总结
singleton:单例模式
-
饿汉模式:(创建的对象不管用不用在内存已经存在了)
public class Pig { // 创建对象 private static Pig pig = new Pig(); private Pig() { } public static Pig getInstance() { return pig; } }
-
懒汉模式
public class Dog { // 声明对象 private static Dog dog; // 省略属性 private Dog() { } // 设计一个类方法返回结果 public static Dog getInstance() { // 双重校验锁 if (dog == null) { synchronized (Dog.class) { if(dog == null) { dog = new Dog(); // 创建对 } } } return dog; // 在单线程情况下没有问题,多线程有问题 } }
-
枚举实现单例
public enum Cat { // 创建对象 TOM; // 就是Cat的对象 private Cat() { } }
adapter(适配器)
就是抽象类实现接口,重写接口大部分方法,留几个抽象方法,让抽象类的子类来重写业务代码
// 抽象类
public abstract class AbstractMyList implements List {
...
}
// 子类
public class MyArrayList extends AbstractMyList implements List {
}
factory(简单工厂模式)
- 对象使用者和创建者分离
// Animal父类
// Bird类,Lion类,Tiger类
// FactoryAnimal
public class FactoryAnimal {
// 设计一个方法创建对象
public static Animal create(String s) { // s就是创建对象的条件
if(s.equals("老虎")) {
return new Tiger();
} else if(s.equals("狮子")) {
return new Lion();
} else if(s.equals("小鸟")) {
return new Bird();
}
return null;
}
}
// 测试类
public class FactoryDemo {
public static void main(String[] args) {
// 消费,获取对象
Animal tiger = FactoryAnimal.create("老虎");
Animal lion = FactoryAnimal.create("狮子");
FactoryAnimal.create("小鸟");
}
}
属性文件(资源文件)的解析
从属性文件中读取键值对
- Properties:基于HashTable的集合,读取文件中的键值对
- IO流:输入流,输入字节流:FileInputStream
注意:键值对只能保存在.properties文件里面
有三种方式
-
使用传统的IO
public class PropertiesDemo { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("D:\\code\\javase\\day1230-singleton2-properties-reflect\\rescource\\username.properties"); Properties pp = new Properties(); pp.load(fis); // 遍历集合pp // Set entries = pp.entrySet(); // System.out.println(entries); String admin = pp.getProperty("admin");// 根据键取值 System.out.println(admin); } }
-
字节码对象获取流
在模块里面可以创建普通文件夹
字节码对象方式获取流,文件最终必须被编译到class文件存放的位置
字节码对象获取流参数的规则:前必须带/,若资源文件没有再包中,包的路径可以省略
注意:资源文件需要放入资源文件夹
public class PropertiesDemo2 { public static void main(String[] args) throws IOException { InputStream is = PropertiesDemo2.class.getResourceAsStream("/1.properties"); Properties pp = new Properties(); pp.load(is); // 从集合取值 String username = pp.getProperty("username"); } }
- 使用类加载器获取输入流
public class PropertiesDemo3 { public static void main(String[] args) throws IOException { // 获取类加载器 ClassLoader classLoader = PropertiesDemo3.class.getClassLoader();// 通过字节码对象来获取类加载器(对象) // ClassLoader loader = Thread.currentThread().getContextClassLoader();// 通过当前线程获取类加载器 // 获取流 InputStream is = classLoader.getResourceAsStream("1.properties"); Properties pp = new Properties(); pp.load(is); System.out.println(pp.getProperty("username")); } }
-
例题
public class PropertiesDemo4 { public static void main(String[] args) throws IOException { // 使用类加载器获取流 // InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("123.properties"); // 字节码文件获取 InputStream is = PropertiesDemo4.class.getResourceAsStream("/123.properties"); Properties pp = new Properties(); pp.load(is); Collection values = pp.values(); ArrayList<Integer> list = new ArrayList<>(); for (Object o : values) { list.add(Integer.parseInt(String.valueOf(o))); } System.out.println(Collections.max(list)); } }
设计工具类
Arrays:
Collections
工具类特征:1、外部类不能创建对象 2、里面全部是类方法
工具类的类名:XxxUtil、XxxUtils、XxxTool、XxxTools
- 设计一个复制文件的工具类
/**
* 设计一个复制文件的工具类
*/
public class CopyFileUtil {
// 私有化构造方法
private CopyFileUtil(){}
// 类方法
public static void copy(String src,String dest) throws IOException {
// 省略参数的判断
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dest));
byte[] bytes = new byte[1024];
int count; // 读到字节个数
while((count = bis.read(bytes)) != -1) {
bos.write(bytes,0,count);
bos.flush();
}
}
}
反射
1、java程序的运行状态,用字节码对象,Class
2、反射:操作字节码对象的一个技术
3、怎样获取类的字节码对象
- 类名.class
Class c1 = ReflectDemo.class;
-
对象.getClass()
Class<? extends ReflectDemo> c2 = rd.getClass();
-
Class.forName(“完全限定名:包名 + 类名”)
Class<?> c3 = Class.forName(“cn.itsource.reflect.ReflectDemo”);
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Class<ReflectDemo> c1 = ReflectDemo.class; // 获取类字节码对象的方式一
ReflectDemo rd = new ReflectDemo();
Class<? extends ReflectDemo> c2 = rd.getClass(); // 获取类字节码对象的方式二
// Class.forName("完全限定名:包名 + 类名");
Class<?> c3 = Class.forName("cn.itsource.reflect.ReflectDemo"); // 获取类字节码对象的方式三
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
}
}
-
获取其他的字节码对象
public class ReflectDemo2 { public static void main(String[] args) throws Exception { // 获取其他的字节码对象 // 1、接口 // Class<List> c1 = List.class; // List<Object> list = new ArrayList<>(); // Class<? extends List> c2 = list.getClass(); // Class<?> c3 = Class.forName("java.util.List"); // System.out.println(c2 == c3); // 2、枚举 // Class<GenderEnum> c1 = GenderEnum.class; // Class<? extends GenderEnum> c2 = GenderEnum.MAN.getClass(); // System.out.println(c1 == c2); // Class<?> c3 = Class.forName("cn.itsource.reflect.GenderEnum"); // 3、数组 // int[] arr1 = {1,2,3}; // Class<? extends int[]> c1 = arr1.getClass(); // Class<int[]> c2 = int[].class; // System.out.println(c1 == c2); // 基本数据类型 // Class<Integer> c1 = int.class; // Class<Integer> type = Integer.TYPE; // Class<Integer> c3 = Integer.class; // Class<Void> c4 = void.class; } } enum GenderEnum { MAN; }
-
反射的API
一个类里面:属性(字段)、构造方法、方法
1. java.lang.Class:字节码对象
2. java.lang.reflect.Constructor:构造方法对象
3. java.lang.reflect.Method:方法对象
4. java.lang.reflect.Field:字段对象(属性对象)
public class ReflectDemo3 {
public static void main(String[] args) throws Exception {
// 使用反射操作Person类
Class<Person> c = Person.class; // 获取Person的字节码对象
// 获取字节码对象里面字段
// c.getFields(); // 获取字节码对象里面所有public修饰的字段
// c.getDeclaredFields(); // 获取字节码对象里面所有访问修饰的字段
//
// c.getField("name"); // 获取指定名的字段(public修饰)
// c.getDeclaredField("name"); // 获取指定名的字段(所有修饰)
// Field[] fields = c.getFields();
// System.out.println(fields.length);
// System.out.println(Arrays.toString(fields));
// Field[] fields = c.getDeclaredFields();
// System.out.println(fields.length);
// Arrays.stream(fields).forEach(System.out::println);
// Field name = c.getField("name");
// System.out.println(name);
// Field gender = c.getField("gender");
// System.out.println(gender);
// Field gender = c.getDeclaredField("gender");
// System.out.println(gender);
// 获取构造方法
// c.getConstructors(); // 获取public修饰构造方法
// c.getDeclaredConstructors();
// c.getConstructor(String.class); // 获取public修饰,有一个String类型参数的构造方法,String.class 参数的字节码对象
// c.getDeclaredConstructor(String.class,String.class);
// 获取方法
// c.getMethods();
// c.getDeclaredMethods();
// c.getMethod("方法名字",参数的字节码对象);
// c.getDeclaredMethod("方法名",参数的字节码对象);
}
}
person类
public class Person {
public String name;
protected String gender;
int age;
private String address; // 地址
public Person() {
}
protected Person(String name) {
this.name = name;
}
Person(String name, String gender) {
this.name = name;
this.gender = gender;
}
private Person(String name, String gender, int age, String address) {
this.name = name;
this.gender = gender;
this.age = age;
this.address = address;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", gender='" + gender + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
private String getAddress() {
return address;
}
private void setAddress(String address) {
this.address = address;
}
}
-
使用反射创建对象
public class ReflectDemo4 { public static void main(String[] args) throws Exception { Class<Person> c = Person.class; // Constructor<Person> constructor = c.getConstructor(); // // 创建对象 // Person p = constructor.newInstance(); // System.out.println(p); Constructor<Person> constructor = c.getDeclaredConstructor(String.class, String.class, int.class, String.class); // private修饰的构造不能直接访问 // 修改状态(跳过检查机制) constructor.setAccessible(true); // 创建对象 Person p = constructor.newInstance("aa", "男", 18, "九眼桥某酒馆"); // 操作方法 // Method m1 = c.getMethod("getName"); // 执行方法 // m1.invoke(对象名,参数); // Object o = m1.invoke(p); // System.out.println(o); // c.getMethod("方法名",参数的字节码对象); // Method m2 = c.getMethod("setName", String.class); // m2.invoke(p,"龙泽蘋蘋"); // Method m3 = c.getDeclaredMethod("getAddress"); // m3.setAccessible(true); // Object o = m3.invoke(p); // System.out.println(o); Method m4 = c.getDeclaredMethod("setAddress", String.class); m4.setAccessible(true); m4.invoke(p,"某某小区某某栋"); System.out.println(p); // 操作字段 // Field name = c.getField("name"); // // 对字段进行取值,赋值 // name.get(对象名); // 获取指定对象的指定字段的值 // Object o = name.get(p); // 获取p对象里面name字段的值 // System.out.println(o); // Field address = c.getDeclaredField("address"); // address.setAccessible(true); // Object o1 = address.get(p); // System.out.println(o1); // name.set(对象名,修改新值); // name.set(p,"华泽蘋蘋"); // System.out.println(p); // address.set(p,"池袋某大厦"); // System.out.println(p); } }
小结
1、设计模式:掌握单例模式
饿汉
懒汉:双重校验锁
枚举
2、解析Properties文件
IO流:对文件路劲没有要求
字节码对象获取流:要求文件放入资源文件夹,目录从/开始
类加载器获取流
3、工具类,打jar包,使用jar包
4、反射
字节码对象:Class
通过字节码对象获取成员:字段 构造方法 方法
构造方法就是创建对象
字段get set
方法:invoke