单例模式&解析Properties文件&工具类&反射

总结

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("小鸟");
    }
}

属性文件(资源文件)的解析

从属性文件中读取键值对

  1. Properties:基于HashTable的集合,读取文件中的键值对
  2. 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");
    
        }
    }
    
    1. 使用类加载器获取输入流
    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

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值