泛型_反射笔记

1.泛型<>

在集合里面 最早的接触的泛型 <K,V,E,T> T,K, V 参数化类型: 任意引用数据类型 A-Z

泛型的主要作用: 类型自动转换

泛型只在编译期间有效 运行期间泛型是无效 class 泛型已经没有作用(泛型擦除)

1.1 泛型类

public class MyFanXingClass<K, V> {

    private K k;
    private V v;

    //不是泛型方法 :  参数化类型充当形参和返回值罢了
    //set/get里面k,v 严格参照创建MyFanXingClass类对象时候的k  v 类型
    public K getK() {
        return k;
    }

    public void setK(K k) {
        this.k = k;
    }

    public V getV() {
        return v;
    }

    public void setV(V v) {
        this.v = v;
    }

    public V demo(K k1) {
        System.out.println("k1:" + k1);
        return v;
    }

    //泛型方法: 在方法定义上  加一个<K>
    //泛型方法里面  参数化类型与创建对象时候的类型 不一定是一致
    //要参考方法上的: <K,A,V>
    public <K, A> V demo1(K k2, A a) {
        System.out.println("k2:" + k2);
        System.out.println("a:" + a);
        return null;
    }

    //静态方法: 类
    //在一个泛型类里面  有静态方法
    //前提: 参数化类型充当方法的形参  返回值
    //这个静态方法必然就是一个泛型方法
    public static <K, T> T demo2(K k3) {
        System.out.println("k3:" + k3);
        return null;
    }

}

1.2 泛型接口

场景:
  用户模块:  User.java
    crud
  商品模块:
     crud
  订单模块:
     crud
public interface BaseDao<T, S> {

    void add(T t);

    void delete(S s);

    void select(S s);

    void update(T t);
}

public abstract class BaseDaoImpl<T, S> implements BaseDao<T, S> {
    //T  S 模拟: MP mybatis-plus.jar   BaseMapper.java
    //获得参数化类型的真实类型
    //反射
    @Override
    public void add(T t) {

    }
    //.................

}
public interface UserDao extends  BaseDao<User,String> {

    //用户模块独有的功能方法

}
public class UserDaoImpl extends BaseDaoImpl<User, String> implements UserDao {

}

1.3 泛型上/下限

public class FanXingClass<T extends Number> {

    //上限
    //T 可以是任意的引用数据类型  Object的子类
    //T 只能是Number类的子类 也可以Number类

    //下限
    // ? 泛型通配符  Class  统配T 的任意类型
    public void a(FanXingClass<? super Number> obj) {
    }

    //下限: ? ArrayList 或者 ArrayList的父类
    public void b(Class<? super Comparable<T>> clazz) {

    }

    // ? 统配所有的参数化类型
    public void c(Class<?> clazz) {

    }

    public static void main(String[] args) {
        FanXingClass<Number> fanXingClass = new FanXingClass<>();

        Class<AbstractList> listClass = AbstractList.class;
//        fanXingClass.b(listClass);

//
//        fanXingClass.a(fanXingClass);

//        Object obj = new Object();
//        obj.getClass()

    }

2. 枚举

Thread.State ChronoField ChroneUnit DayOfWeek Month

public enum 枚举类名称{
    //成员
     对象(实例  常量  不可变的  唯一的  单例)
     方法
     属性
     构造
}
public enum MyEnum {
    //维护不可变的数据

    //    对象(实例  常量  不可变的  唯一的  单例)
//    方法
//    属性
//    构造
    //枚举类的对象(默认通过无参构造创建对象)
    MONDAY(1, "星期一") {
        //方法重写
        @Override
        public void a() {
            System.out.println("重写a。。。。。。");
        }

    },
    TUESDAY(2, "星期二"),
    SUNDAY(7, "星期日");
    private Integer id;
    private String name;

    public void a() {
        System.out.println("a.....");
    }

    public final Integer getId() {
        return id;
    }

    public final String getName() {
        return name;
    }


    MyEnum(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

//    MyEnum() {
//        //默认存在无参构造 (所有的构造都是private)
//    }
}

2.1 泛型+枚举类

根据数据分析 设计类 设计方法

{
    "message": "CityId100030200不在返回之内,",
    "status": 403
}
{
    "message": "success",
    "status": 200,
    "data":{
        //什么类型的额数据  不定的  url(接口)--->作用到程序里面的方法
    }

https://www.sojson.com/blog/305.html

http://t.weather.itboy.net/api/weather/city/101030100

@Setter
@Getter
@ToString
public class ServerResponseResult<T> {
    //里面所有的构造都是私有的
    private ServerResponseResult() {
    }

    private String message;//成功/失败的信息
    private Integer status;//成功/失败的状态  肯定都是固定的
    private T data;//成功时候的数据

    private ServerResponseResult(String message, Integer status, T data) {
        this.message = message;
        this.status = status;
        this.data = data;
    }

    private ServerResponseResult(String message, Integer status) {
        this.message = message;
        this.status = status;
    }

    //通过静态方法处理: 类对象
    public static <T> ServerResponseResult<T> success(String message, Integer status, T data) {
        return new ServerResponseResult<>(message, status, data);
    }

    public static <T> ServerResponseResult<T> success(T data) {
        return new ServerResponseResult<>(CodeEnum.SUCCESS.getMsg(), CodeEnum.SUCCESS.getCode(), data);
    }

    public static <T> ServerResponseResult<T> error(String message, Integer status) {
        return new ServerResponseResult<>(message, status);
    }

    public static <T> ServerResponseResult<T> error() {
        return new ServerResponseResult<>(CodeEnum.ERROR.getMsg(), CodeEnum.ERROR.getCode());
    }
}

3.单例

单例模式。 java语言23种设计模式其中之一。

在一个进程里面有且只有一个实例。 (一个进程可以有多个线程的 在不同的线程里面 只有1个对象)

多例 vs 单例

  1. 饿汉模式 (没有线程安全问题 )
//1.将构造变成private修饰
//2.提供静态成员变量 并初始化对象
//3.提供静态的方法 直接返回对象
public class UserInfo {

    private UserInfo() {
    }

    private static UserInfo userInfo = new UserInfo();

    public static UserInfo getInstance() {
        return userInfo;
    }
    
}
   //弊端: 没有体现懒加载思想(想什么时候用就什么时候去创建)
    //类与对象: 对成员变量尽可能不要初始化

2.懒汉模式

//1.将构造变成private修饰
//2.提供静态成员变量
//3.提供静态的方法

public class UserInfo {

    private UserInfo() {
    }

    private static UserInfo userInfo;//null

    public static UserInfo getInstance() {
        if (userInfo == null) {
            userInfo = new UserInfo();
             //什么时候需要  就什么时候出初始化  体现懒加载的思想  有可能会出现线程安全的问题
        }
        return userInfo;
    }
}
Thread-1:com.javasm.singlton.UserInfo@62b7b91
Thread-0:com.javasm.singlton.UserInfo@22e7a307
Thread-3:com.javasm.singlton.UserInfo@22e7a307

解决方式1

同步方法: 能解决安全问题  性能很低
同步代码快:  
 public static  UserInfo getInstance() {
        synchronized (UserInfo.class) {
            if (userInfo == null) {
                userInfo = new UserInfo();
                //什么时候需要  就什么时候出初始化
            }
        }
        return userInfo;
    }

解决方式2

double check lock  DCL
 public static UserInfo getInstance() {
        if (userInfo == null) {//dcl
            synchronized (UserInfo.class) {
                if (userInfo == null) {
                    userInfo = new UserInfo();
                    //什么时候需要  就什么时候出初始化
                }
            }
        }
        return userInfo;
    }

解决方式3:

DCL还是有弊端:
  由于计算机内部具有指令重排特性: 提高程序效率    jvm也是具备特性
    创建对象:  31.分配空间 2ms
      2.执行构造初始化成员变量 10ms
      3.赋值 内存地址赋值给引用 1ms
      
      一共需要13ms完成对象的创建:
        只执行了: 1 3  3ms 
            2 用属性
      SpringMVC  Controller 单例: 属性必然要初始化 
    
    限制指令重排.
  volatile 功能与synchronized相似  都是解决数据可见性问题的,
  synchronized: 原子性  顺序性  可见性
  volatile: 可见性 顺序性 不能保证原子性   i++; int temp = i  temp=i+1; i = temp;
            限制指令重排.  效率快
public class UserInfo {

    private UserInfo() {
    }

    private volatile static UserInfo userInfo;//null
    //10 个线程 都在第一个if
    //1个线程  new

    public static UserInfo getInstance() {
        if (userInfo == null) {//dcl
            synchronized (UserInfo.class) {
                if (userInfo == null) {
                    userInfo = new UserInfo();
                    //什么时候需要  就什么时候出初始化
                }
            }
        }
        return userInfo;
    }
}

机器码+汇编码

序列化

4. volatile

在多线程环境下,自定义一个id生成器:  用户的id  整型
public class IDGenerator {
    private static  int id;//0

    public  void idIncrease() {
        id++;//线程安全
        //3步来完成  9001
//        int temp = id;
//        temp = id+1;
//        id = temp;
    }

    public int getId() {
        return id;
    }

}
public class IDGenerator {


//    private static  int id;//0
//    AtomicInteger/AtomicLong
//    private static AtomicInteger id = new AtomicInteger();
    private static LongAdder id = new LongAdder();
    //性能优于AtomicInteger/AtomicLong  减少乐观锁的重试次数
    public void idIncrease() {
//        id++;//线程安全
        //3步来完成  9001
//        int temp = id;
//        temp = id+1;
//        id = temp;
//        id.incrementAndGet();
        id.increment();
    }

    public int getId() {
        return id.intValue();
    }

}
 public static void main(String[] args) {

        IDGenerator idGenerator = new IDGenerator();
        //数据分析
        List<Thread> list = new ArrayList<>(50);
        for (int i = 0; i < 100; i++) {
            Thread thread = new Thread(() -> {
                for (int i1 = 0; i1 < 100; i1++) {
                    idGenerator.idIncrease();
                }
            });
            list.add(thread);
        }

        list.forEach(thread -> thread.start());
        list.forEach(thread -> {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        //让100个子线程执行完毕之后  在主线程里面拿到最终的id值
        //等待着100个线程死亡之后 才允许main逻辑

        System.out.println("main:" + idGenerator.getId());//10000

    }
}

5.注解

注释: 阐释代码含义 给程序员

注解: 解释说明 给程序看的 程序解析注解 @解释名

作用: 使用框架集成开发的时候: 1. xml文件配置 2.注解开发

使用位置: 类上 接口上 方法 属性 形参

高内聚  低耦合
1.xml文件配置 耦合度比较低  几个框架  只需要几个xml就可以集成  容易维护
2.注解开发  效率高  耦合度高 不太容易维护  SpringBoot 全注解

5.1 内置注解

@SuppressWarnings("all")
public class Demo extends Object {

    @Override
    public String toString() {
        return super.toString();
    }

    @Deprecated
    public void a() {

    }
    
    public void b() {
        List list = new ArrayList();
    }

    public void c() {
        List list = new ArrayList();
    }
}

5.2 元注解

对注解进行注解。(解释说明)

1. @Target 标识当前注解的使用位置    
2. @Retention 标识注解在哪个范围内有效的

3. @Documented 当我们使用javadoc 注解也会出现的文档文件中
4. @inherited 标识子类集成父类的注解
5. @FunctionalInterface 函数式接口--->修饰接口

5.3 自定义注解

使用jdk提供的元注解定义注解

public @interface 注解名称{
    //组成部分: (数据/参数类型)成员变量
    //可以支持数据的数据类型:
    //1.基本数据类型
    //2.String
    //3.Class
    //4.枚举
    //5.以上所有类型的数组  
    //6.注解类型(解释参数)
}
@Target({ElementType.TYPE, ElementType.FIELD,ElementType.METHOD})
//如果一个注解里面 参数只有value 参数名称可以省略
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation {
    //制定参数
    int id() default 1000;

    String name() default "无名氏";

    String[] hobby() default {};

    double score() default 100;

    Class<?>[] clazz() default {Student.class,Object.class};

    DayOfWeek day() default DayOfWeek.MONDAY;

}

5.4 使用注解

@MyAnnotation(id = 1001, hobby = {"code", "music", "game"}, score = 100, clazz = {Student.class})
public class Student {
    @MyAnnotation
    //不指定参数的数据  获取的全部都是默认值
    public void info() {

    }
}

6.反射

泛型: List 是否可以存储 String。 反射

注解: 获得参数的数据? 反射

反射是框架的灵魂。

java语言具有动态性。 java语言有反射机制

Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键
它却有着一个非常突出的动态相关机制:Reflection。这个字的意思是“反射、映象、倒影”,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。这种“看透class”的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。

操作class文件组成部分的技术.

将我们整个类里面的组成部分封装成相对应类。

类属性--->Filed
类的方法--->Method
类的构造--->Constructor
类里面的注解--->Annotation

正常开发中: 创建一个新的对象 new 为何反射?

框架集成开发的时候: 动态的将前台页面的用户注册的信息 自动封装成一个用户对象? 反射

name=jim&pass=1234&phone=17365
// 参数名称==类里面的属性名称  private      set注入    User user = 反射.new    

6.1 操作属性

反射实现: 模拟前台页面数据提交到对象
  name=jim&pass=1234&phone=17365
 private static void demo1() {
        //name=jim&pass=1234&phone=17365
        String name = "jim";
        String pass = "1234";
        String phone = "17365";
        int id = 1001;

        //约定大于配置
        Map<String, Object> params = new HashMap<>(16);
        params.put("name", name);
        params.put("pass", pass);
        params.put("phone", phone);
        params.put("id", id);
        //数据自动注入对象中
        //反射: 操作正在运行的类或者接口或者枚举类的class内容  Class类对象
        try {
            //1.获得Class类对象
            Class<?> clazz = Class.forName("com.javasm.reflect.UserInfo");
            //2.反射创建UserInfo对象(构造方法)--->无参构造
            //2.1 调用Class类的方法 newInstance() --->无参构造 Constructor
            UserInfo userInfo = (UserInfo) clazz.newInstance();
            //3.属性赋值(直接通过属性/set方法(重点))--->set注入
            //3.1 通过属性
//            Field[] fields = clazz.getFields();//获得public修饰的属性
//            System.out.println(Arrays.toString(fields));//[]
//            fields = clazz.getDeclaredFields();//类里面所有的属性
//            System.out.println(Arrays.toString(fields));

//            clazz.getDeclaredField(fieldName); 根据属性名称获得特定的属性
//            clazz.getField(fieldName)

            params.forEach((fieldName, fieldValue) -> {
                try {
                    //根据属性名称获得特定属性
                    Field field = clazz.getDeclaredField(fieldName);
                    field.setAccessible(true);//开启权限访问
                    //对属性赋值 ---> 体现在userInfo对象里面
                    //public void set(Object obj, Object value)
                    field.set(userInfo, fieldValue);
                } catch (NoSuchFieldException | IllegalAccessException e) {
                    e.printStackTrace();
                }
            });
            System.out.println(userInfo);

        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        }
    }

6.2 操作方法

6.3 操作构造

//2.获得UserInfo的对象
//            Constructor<?>[] constructors = aClass.getConstructors();//只能获取public修饰的构造方法
//            System.out.println(Arrays.toString(constructors));
//            Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();//类里面所有的构造方法
//            System.out.println(Arrays.toString(declaredConstructors));

            //通过有参创建对象
            //public Constructor<T> getConstructor(Class<?>... parameterTypes) 有参构造方法的参数类型
            Constructor<?> constructor = aClass.getConstructor(Integer.class, String.class, String.class, String.class);
            UserInfo userInfo =(UserInfo) constructor.newInstance(1, "admin", "1111", "232334");
            System.out.println(userInfo);

            //new clone 序列化  反射(Class.newInstance/Constructor.newInstance)

6.4 操作注解

昨天 泛型 接口 获得某个城市天气数据 http://t.weather.itboy.net/api/weather/city

http://t.weather.itboy.net/api/weather/city == 后台写的一个方法 (映射出来了一个路径)

public static void main(String[] args) {

        //注解在哪个类
        //注解在哪个类哪个方法上
        try {
            Class<?> clazz = Class.forName("com.javasm.reflect.UserController");
            PathAnno annotation1 = clazz.getAnnotation(PathAnno.class);
            System.out.println("annotation1:"+annotation1.value());

            Method method = clazz.getMethod("selectAllUser");
            Annotation[] annotations = method.getAnnotations();
            for (Annotation annotation : annotations) {
                if (annotation instanceof PathAnno) {
                    PathAnno pathAnno = (PathAnno) annotation;
                    String value = pathAnno.value();
                    System.out.println(value);
                } else if (annotation instanceof MyAnnotation) {
                    MyAnnotation myAnnotation = (MyAnnotation) annotation;
                    System.out.println(myAnnotation.id());
                    System.out.println(myAnnotation.name());
                    System.out.println(myAnnotation.day());
                    System.out.println(myAnnotation.score());
                    System.out.println(Arrays.toString(myAnnotation.clazz()));
                    System.out.println(Arrays.toString(myAnnotation.hobby()));
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

    }

6.5 泛型擦除

public static void main(String[] args) {
        //List<Integer> 是否可以存储 String。   反射
        List<Integer> list = new ArrayList<>(10);
        list.add(10);
        //编译期间有效   运行期间: 存储的数据  Object
//        list.add("abc");
        // add()  ---> Method--->invoke
        Class<List> listClass = List.class;
        try {
            Method addMethod = listClass.getMethod("add", Object.class);
            addMethod.invoke(list, "hello");
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        System.out.println("list:" + list);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值