您的位置:首页 > 编程语言 > Java开发

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();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: