javawebday65(泛型、通配符、注解、反射 注解使用)
2018-03-29 13:55
531 查看
泛型 1、具有一个或多个泛型变量的类型被称之为泛型类 class A<T>{} 2、在创建泛型类实例时,需要为其类型变量赋值 A<String> a = new A<String>(); 如果创建实例时,不给类型变量赋值,那么会有一个警告。 3、泛型方法:具有一个或多个类型变量的方法,称之为泛型方法 class A<T>{ public T fun(T t1){ } } fun()方法不是泛型方法,是泛型类中的一个方法 public <T>T fun (T t1){} -->是泛型方法 泛型方法和泛型类没什么关系,泛型方法不一定非要在泛型类中。 4、泛型在类中或方法中的使用 泛型类中使用泛型 成员类型 返回值和参数类型 局部变量的引用上 class A<T>{ private T bean;//泛型可在成员变量上使用 public T fun(T t){}//泛型可以在类中的方法上(返回值和参数类型)使用 public void fun2(){//泛型还可以在局部变量的引用类型上使用 T b=... new T();//不行 } } 5、泛型的继承和实现 class A<T>{} class AA extends A<String>{}//不是泛型类,只是他爸爸是泛型类 5.1、继承泛型类 子类不是泛型类:需要给父类传递类型常量 当给父类传递的类型常量为String时,那么在父类中所有T都会被String替换 子类是泛型类,可以给父类传递类型常量,也可以传递类型变量 class AA1 extends A<Integer>{} class AA3<E> extends A<E>{} 泛型的通配符 1、通配符使用的场景 方法的形参 2、通配符的优点 使方法更加通用 3、通配符分类 无界通配:? 子类限定:? extend Object 父类限定: ? super Integer 4、通配符缺点 使变量使用上不再方便 无界:参数和返回值为泛型的方法,不能使用 子类:参数为泛型的方法不能使用 父类:返回值为泛型的方法不能使用 5、比较通配符 boolean addAll(Collection<E> c) List<Number> numList = new ArrayList<Number>(); List<Integer> intList = new ArrayList<Integer>(); numList.addAll(intList);//addAll(Collection<Number> c),传递的是List<Integer> boolean addAll(Collection<? extends E> c) List<Number> numList = new ArrayList<Number>(); List<Integer> intList = new ArrayList<Integer>(); numList.addAll(intList);//addAll(Collection<? extends Number> c),传递的是List<Integer> 注解【配置文件 需要有人读 否则无意义,往往是框架读比如tomcat】 1、什么是注解 语法:@注释名称 注解的作用:替代xml配置文件 servlet3.0中,就可以不再使用 1141f web.xml,而是所有配置都使用注解 注解是由框架来读取使用 2、注解 定义注解类:框架的工作 使用注释:我们的工作 读取注释(反射):框架的工作 3、定义注解类 class A{} interface A{} enum A{} @interface A{} 所有的注解都是Annotation的子类 4、使用注解 可以把注解作用在:类、方法、属性、构造器、方法参数、局部变量也可以把注解作用在包上[没啥用] @Retention(RetentionPolicy.RUNTIME) public @interface MyAnn{} 下面的代码会出错 @MyAnn package xx; public class A{} 因为java不让这么注解包,如果想给包添加注解必须再创建一个文件:package-info.java文件,然后在这个方法中给出对包的注解 package-info.java @MyAnn package xx 反射包上的注解 Package p = Package.getPackage("my.xx"); MyAnn myAnn = p.getAnnocation(MyAnn.class); 注解的作用目标 类 方法 构造器 参数 局部变量 包 5、注解的属性 定义属性 格式:类型 属性名(); @interface MyAnno1{ int age(); String name(); } 使用注解时给属性赋值 @MyAnno1(age=10,name="zhangSan") 注解属性的默认值:在定义注解时,可以给注解定义默认值 int age() default 100; 在使用注解时,可以不给带有默认值的属性赋值 名为value的属性的特权 当使用注解时,如果只(仅一个的时候)给名为value的属性赋值时,可以省略"value=", 例如@MyAnno1(value="hello")可以书写成@MyAnno1("hello") 注解属性的类型 8中基本类型 String Enum Class 注解类型 以上类型的一维数组类型 包装类不行比如Integer 当给数组类型的属性赋值时,若数组元素的个数为1时,可以省略大括号 @MyAnno1( a=100, b="hello", c=MyEnum1.A, d=String.class, e=@MyAnno2(aa=1,bb="2"), f={"a","b"}, h=100 ) public class Demo3 { } @interface MyAnno1{ int a(); String b(); MyEnum1 c(); Class d(); MyAnno2 e(); String[] f(); int[] h(); } @interface MyAnno2{ int aa(); String bb(); } //枚举要求是其中的一个 enum MyEnum1{ A,B,C } 6、注解的作用目标限定以及保定策略限定 6.1让一个注解,它的作用目标只能在类上,不能在方法上,这就叫作用目标的限定 在调用注解时,给注解添加注解,这个注解是@Target 枚举就几个选项 @Target(value={ElementType.TYPE,ElementType.METHOD,ElementType.FIELD}) @interface MyAnno1{ } 6.2保留策略 源代码文件(source):注解只在源代码中存在,当编译时就被忽略了 字节码文件(class):注解在源代码中存在,然后编译时会把注解信息放到了class文件,但JVM在加载类时,会忽略注解 JVM中(runtime):注解在源代码、字节码文件中存在,并且在JVM加载类时,会把注解加载到JVM内中(唯一可反射的注解) 6.3、限定注解的保留策略 使用 @Retention(RetentionPolicy.RUNTIME) @interface MyAnno1{ } 7、读取注解(反射) 反射泛型信息 Class-->Type getGenericSupperclss() Type-->ParameterizedType:把Type强转成ParameterizedType类型 ParameterizedType-->参数化类型=A<String> ParameterizedType:Type[] getActuallTypeArguments(),A<String>中的String Type[]就是Class[],就得到了类型参数 abstract class A<T>{ public A(){ /* * 获取子类传递的泛型信息,得到一个class */ // Class clazz = this.getClass();//得到子类的类型 // Type type = clazz.getGenericSuperclass();//获取传递给父类的参数化类型 // ParameterizedType pType = (ParameterizedType) type;//就是A<String> // Type[] types = pType.getActualTypeArguments();//就是一个Class数组 // Class c = (Class) types[0];//就是String // Class c = null; // System.out.println(c.getName());//String或Integer Class c= (Class) ((ParameterizedType) this.getClass().getGenericSuperclass()) .getActualTypeArguments()[0]; System.out.println(c.getName()); } } 反射注解 1、要求 注解的保留策略必须是RUNTIME 2、反射注解需要从作用目标上返回 类上的注解,需要使用Class获取 方法上的注解,需要Method来获取 构造器的注解,需要Constructor来获取 成员上的,需要Field来获取 Class: Method、Constructor、Field:AccessibleObject 都有一个方法: Annotation getAnnotation(Class):返回目标上指定类型的注解 Annotation[] getAnnotations:返回目标上所有注解
public class Demo2 { @Test public void fun1(){ //数组 Object[] objs = new Object[10]; List list = new ArrayList(); String[] strs = new String[10]; //1.4之前不行 1.5会了 List<String> strList = new ArrayList<String>(); Object[] objArray = new String[10]; objArray[0] = new Integer[100]; //ArrayStoreException // List<Object> objList= new ArrayList<String>(); //泛型擦除 在虚拟机中<>会被去掉 // objList.add(new Integer(100)); /* * 泛型引用和创建两端,给出的泛型变量必须相同 */ //fun2("hell");//Object o = "hell"; } public void fun2(){ List<Integer> integerList = new ArrayList<Integer>(); print(integerList);//List<Object> list = integerList List<String> stringList = new ArrayList<String>(); print(stringList); } /* * 其中的?就是通配符 * 通配符只能出现在左边,即不能在new时使用通配符 * List<? extends Object> list = new ArrayList<String>(); */ /* * ?表示一个不确定的类型,它的值会在调用时确定下来 */ public void print(List<? extends Object> list){ /* * 当使用通配符时,对泛型类中的参数为泛型的方法起到了副作用,不能使用 */ //list.add("hello"); /* * 当使用通配符时,泛型类中返回值为泛型的方法,也作废了 */ Object s = list.get(0); /* * 通配符好处:可以使泛型类型更加通用。尤其是在方法调用时形参使用通配符 */ } public void fun3(){ List<Integer> intList = new ArrayList<Integer>(); print1(intList); List<Long> longList = new ArrayList<Long>(); print1(longList); } /* * 给通配符添加了限定 * 只能传递number或其子类型 * 子类通配符对通用性产生了影响,但使用形参更加灵活 * */ public void print1(List<? extends Number> list){ /* * 参数为泛型的方法还是不能使用 */ // list.add(new Integer(100)); /* * 返回值为泛型的方法可用了 */ Number number = list.get(0); } public void print2(List<? super Integer> list){ /* * 给通配符添加了限定 * 只能传递Integer类型,或其父类型 */ /* * 参数为泛型的方法可以使用了 */ list.add(new Integer(100)); /* * 返回值为泛型的方法还是不能使用 */ Object a = list.get(0); } public void fun4(){ List<Integer> intList = new ArrayList<Integer>(); print2(intList); List<Number> longList = new ArrayList<Number>(); print2(longList); List<Object> objList = new ArrayList<Object>(); print2(objList); } }
@MyAnno1 public class Demo1 { //重写父类的方法如果不是重写的报错 帮你检查是否是父类的方法 @Override public String toString(){ return null; } //@Deprecated 作用在方法上,标记该方法为作废方法 //@SuppressWarnings:作用在方法上,压制警告 @MyAnno1 private String name; @MyAnno1 public void Demo1(){ } @MyAnno1 public void fun1(){ } public void fun2(@MyAnno1 String name){ @MyAnno1 String username="hh"; } } /** * 定义注解 * @author Administrator * */ @interface MyAnno1{ }
public class Demo1 { @Test public void fun1(){ new B();//class my.demo1.B } } abstract class A<T>{ public A(){ /* * 获取子类传递的泛型信息,得到一个class */ // Class clazz = this.getClass();//得到子类的类型 // Type type = clazz.getGenericSuperclass();//获取传递给父类的参数化类型 // ParameterizedType pType = (ParameterizedType) type;//就是A<String> // Type[] types = pType.getActualTypeArguments();//就是一个Class数组 // Class c = (Class) types[0];//就是String // Class c = null; // System.out.println(c.getName());//String或Integer Class c= (Class) ((ParameterizedType) this.getClass().getGenericSuperclass()) .getActualTypeArguments()[0]; System.out.println(c.getName()); } } class B extends A<String>{ }
public class Demo2 { @Test public void fun1(){ /* * 1、得到作用模版 */ Class<A> c = A.class; /* * 2、获取指定类型的注解 */ MyAnno1 myAnno1 = (MyAnno1) c.getAnnotation(MyAnno1.class); System.out.println(myAnno1.name() + "," + myAnno1.age() +"," +myAnno1.sex()); } @Test public void fun2() throws NoSuchMethodException, SecurityException{ /* * 1、得到作用模版 */ Class<A> c = A.class; Method method = c.getMethod("fun1"); /* * */ /* * 2、获取指定类型的注解 */ MyAnno1 myAnno1 = method.getAnnotation(MyAnno1.class); System.out.println(myAnno1.name() + "," + myAnno1.age() +"," +myAnno1.sex()); } } @MyAnno1(name="A",age=1,sex="男") class A{ @MyAnno1(name="fun1方法",age=2,sex="女") public void fun1(){ } } @Retention(RetentionPolicy.RUNTIME) @interface MyAnno1{ String name(); int age(); String sex(); }
public class Demo2 { private QueryRunner qr = new TxQueryRunner(); /** * dbUtils * @throws SQLException */ public void addUser(User user) throws SQLException{ String sql = ""; Object[] params = {}; qr.update(sql,params); } public void addCategory(Category category) throws SQLException{ String sql = ""; Object[] params = {}; qr.update(sql,params); } } <bean class = "my.User",table="tb_user"> <property name="username" column="uname" /> </bean> class BaseDAO<T>{ private QueryRunner qr = new TxQueryRunner(); private Class<T> beanClass; //通过注解来完成类似hibernate的缩减版 public BaseDAO(){ beanClass = (Class) ((ParameterizedType)this.getClass() .getGenericSuperclass()).getActualTypeArguments()[0]; } public void add(T bean) throws SQLException{ Field[] fs = beanClass.getDeclaredFields(); String sql = "insert into "+beanClass.getSimpleName()+" values("; for (int i = 0; i < fs.length; i++) { sql += "?"; if(i<fs.length-1){ sql +=","; } } sql += ")"; Object[] params ={/*参数值是什么*/}; qr.update(sql,params); } public void update(T bean){ } public void delete(String uuid){ } public T load (String uuid){ return null; } public List<T> findAll(){ return null; } } class UserDAO extends BaseDAO<User>{ public void addUser(User user) throws SQLException{ super.add(user); } }
@Table("tb_user")//它的值表示当前类对应的表 public class User { @ID("u_id")//当前属性对应的列名,而且说明这个列是主键 private String uid; @Column("uname") private String uname; private String password;
public @interface ID { String value(); }
相关文章推荐
- Java 理论与实践: 使用通配符简化泛型使用
- Java 理论与实践: 使用通配符简化泛型使用
- Java 理论与实践: 使用通配符简化泛型使用
- 在 Java 的泛型类型中使用通配符
- Java 理论与实践:使用通配符简化泛型使用
- Java 理论与实践: 使用通配符简化泛型使用
- Java 理论与实践: 使用通配符简化泛型使用
- 在 Java 的泛型类型中使用通配符
- java 注解annotation的使用,以及反射如何获取注解
- 23-java基础加强(反射、泛型、注解、动态代理)
- 黑马程序员_java基础加强_静态导入_反射_枚举_注解_内省_泛型_代理
- Java 理论与实践:使用通配符简化泛型使用
- Java基础:泛型类型的子类及通配符的使用
- 在 Java 的泛型类型中使用通配符
- Java 理论与实践: 使用通配符简化泛型使用 (二)
- 黑马程序员--Java基础加强--15.利用反射操作泛型IV【通过反射Method解析泛型方法思路】【通过Method对四种Type子接口类型进行解剖】【使用递归对任意复合泛型类型进行彻底解剖】【个人
- [转贴] Java 理论与实践: 使用通配符简化泛型使用
- 黑马程序员_java中泛型(通配符)与反射技术
- [转贴] Java 理论与实践: 使用通配符简化泛型使用
- 转载 Java 理论与实践: 使用通配符简化泛型使用