注解
什么是注解
- 属于java.annotation包 Annotation是从JDK1.5开始引入的新技术,注解既可以对程序员解释又可以对程序解释
注解与注释的区别
- 注释:对程序员解释代码信息
- 注解:对程序和程序员解释代码信息
注解的作用
- 注解并不是程序本身,却可以对程序作出解释(与注释(comment)类似)
- 可以被其他程序(编译器)读取
注解的格式
- 注解是以“@注释名”在代码中存在的,还可以添加一些参数 例如:@SuppressWarnings(value=“unchecked”)
注解的应用
- 可以附加在package、class、method、field等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制实现对这些数据的访问
内置注解
@Overrlde:定义在java.lang.Override中,此注解只适用于修饰方法,表示一个方法声明打算重写超类中的另一个方法声明
@Deprecated:定义在java.lang.Deprecated中.此注解可以用于修饰方法,属性,类。表示不鼓励使用这样的元素.通常是因为它很危险或者存在更好的选择
@SuppressWarnings:镇压警告,定义在java.lang.SuppressWarnings中用来抑制编译时的警告信息,与前两个注释有所不同.你需要添加参数才能正确使用。这些参数都是已经定义好了的.我们选择性的使用就好了
- @SuppressWarnings(“all”)抑制所有类型的警告信息
- @SuppressWarnings(“unchecked”)抑制单类型的警告信息
- @SuppressWarnings(value={“unchecked”,“deprecation”})抑制多类型的警告信息
public class Test01 {
public static void main(String[] args) {
/**
* 知识点:内置注解
* 含义:Java给我们提供的注解
*/
}
}
class A{
public void method01() {
}
}
class B extends A{
@Override //表示重写父类方法的注解
public void method01() {
}
@Deprecated //表示过时(弃用)方法的注解
public void method02(){
}
@SuppressWarnings("all") //镇压所有警告的注解
public void method03(){
String str;
ArrayList list = new ArrayList();
}
@SuppressWarnings("unchecked") //镇压单类型警告的注解
public void method04(){
String str;
ArrayList list = new ArrayList();
list.add(123);
list.add("aaa");
}
}
元注解
- 元注解的作用:负责注解其他注解,Java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型作说明 这些类型和它们所支持的类在java.lang.annotation包中可以找到 (@Target,@Retention,@Documented,@Inherited )
- @Target:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
- @Retention:表示需要要在什么级别保存该注择信息,用于描述注解的生命周期 (SOURCE < CLASS < RUNTIME)
- @Document:说明该注解将被包含在javadoc中
- @lnherited:说明子类可以继承父类中的该注解
自定义注解
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口
分析:
- @interface用来声明一个注解,格式:public @interface注解名{定义内容} ,其中的每一个方法实际上是声明了一个配置参数.方法的名称就是参数的名称.
- 返回值类型就是参数的类型(返回值只能是基本类型、Class、String、enum)
- 可以通过default来声明参数的默认值
- 如果只有一个参数成员,一般参数名为value()
@Target({ElementType.TYPE,ElementType.METHOD}) //元注解:标识注解的注解
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String str01();
String str02() default "123";
// String value();
String[] value();
}
//@MyAnnotation("123") //注解中只有一个属性,且名称为value时,可只写值,不写键
//@MyAnnotation({"112233","123"}) //属性为数组,String[] value();传参时要传输组
@MyAnnotation(str01="aaa",value={"ccc"}) //有多个属性时,必须同时写上键与值;若属性有默认值,也可不传值
public class Test01 {
}
反射
Java的反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射的基本使用
反射-获取Class文件对象
配置文件
classpath.properties
classPath=com.dream.reflex01.Student //类的全路径名
DSClassPath.properties
classPath=com.dream.reflex02.LocalDataSource,com.dream.reflex02.NetworkDataSource,com.dream.reflex02.OtherDataSource //类的全路径名
DSName.properties
name=本地,网络,其他
public static void main(String[] args) throws Exception {
/**
* 需求:获取字节码文件对象
*/
//获取方式1
Class<?> c1 = Student.class;
//获取方式2
Student stu = new Student();
Class<?> c2 = stu.getClass();
//获取方式3
Properties p = new Properties();
p.load(Test01.class.getClassLoader().getResourceAsStream("classpath.properties"));
String classPath = p.getProperty("classPath");
Class<?> c3 = Class.forName(classPath);
System.out.println(c1 == c2); //true
System.out.println(c1 == c3); //true
}
反射-操作构造方法
学生类
public class Student extends A{
public String name;
private char sex;
private int age;
private String classId;
private String id;
public Student() {
}
private Student(String classId, String id) {
this.classId = classId;
this.id = id;
}
public Student(String name, char sex, int age, String classId, String id) {
this.name = name;
this.sex = sex;
this.age = age;
this.classId = classId;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getClassId() {
return classId;
}
public void setClassId(String classId) {
this.classId = classId;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void eat() {
System.out.println(this.name + "吃饭饭");
sleep();
}
private void sleep() {
System.out.println(this.name + "睡觉觉");
}
@Override
public String toString() {
return name + "\t" + sex + "\t" + age + "\t" + classId + "\t" + id;
}
}
测试类
public static void main(String[] args) throws Exception {
/**
* 需求:利用反射机制操作构造方法(在反射中,构造方法、成员方法和成员变量都被当成对象),实例方法即是成员方法。
*/
//获取Student类的字节码文件对象
Properties p = new Properties();
p.load(Test02.class.getClassLoader().getResourceAsStream("classpath.properties"));
String classPath = p.getProperty("classPath");
Class<?> c = Class.forName(classPath);
//获取该类的 public 构造方法
//Constructor<?>[] constructors = c.getConstructors();
//for (Constructor<?> constructor : constructors) {
// System.out.println(constructor);
//}
//获取该类的所有构造方法
//Constructor<?>[] declaredConstructors = c.getDeclaredConstructors();
//for (Constructor<?> declaredConstructor : declaredConstructors) {
// System.out.println(declaredConstructor);
//}
//利用无参构造创建 Student 对象(1)
//Student stu = (Student) c.newInstance();
//System.out.println(stu);
//利用无参构造创建 Student 对象(2)
//Constructor<?> constructor = c.getConstructor();
//Student stu = (Student) constructor.newInstance();
//System.out.println(stu);
//利用有参构造创建 Student 对象
Constructor<?> constructor = c.getDeclaredConstructor(String.class, char.class, int.class, String.class, String.class);
constructor.setAccessible(true);
Student stu = (Student) constructor.newInstance("张三", '男', 21, "2107","001");
System.out.println(stu);
}
反射-操作属性
public static void main(String[] args) throws Exception {
/**
* 需求:利用反射机制操作属性
*/
//获取Student的字节码文件对象
Properties p = new Properties();
p.load(Test03.class.getClassLoader().getResourceAsStream("classpath.properties"));
String classPath = p.getProperty("classPath");
Class<?> c = Class.forName(classPath);
//获取本类和父类中公有属性的对象
//Field[] fields = c.getFields();
//for (Field field : fields) {
// System.out.println(field);
//}
//获取本类所有属性的对象
//Field[] declaredFields = c.getDeclaredFields();
//for (Field declaredField : declaredFields) {
// System.out.println(declaredField);
//}
Student stu = new Student("张三", '男', 21, "2017", "001");
//设置非私有化属性
Field name = c.getField("name");
name.set(stu,"李四");
//设置私有化属性
Field age = c.getDeclaredField("age");
age.setAccessible(true); //设置修改权限
age.set(stu,23);
System.out.println(stu);
}
反射-操作方法
public static void main(String[] args) throws Exception {
/**
* 需求:利用反射机制操作方法
*/
//获取Student的字节码文件对象
Properties p = new Properties();
p.load(Test03.class.getClassLoader().getResourceAsStream("classpath.properties"));
String classPath = p.getProperty("classPath");
Class<?> c = Class.forName(classPath);
//获取该类及父类的公有方法的对象
//Method[] methods = c.getMethods();
//for (Method method : methods) {
// System.out.println(method);
//}
//获取该类所有方法的对象
//Method[] declaredMethods = c.getDeclaredMethods();
//for (Method declaredMethod : declaredMethods) {
// System.out.println(declaredMethod);
//}
Student stu = new Student("张三", '男', 21, "2107", "001");
//调用公有方法
Method setAge = c.getMethod("setAge", int.class);
setAge.invoke(stu,23);
//调用私有方法
Method sleep = c.getDeclaredMethod("sleep");
sleep.setAccessible(true);
sleep.invoke(stu);
System.out.println(stu);
}
反射-操作数组
public static void main(String[] args) {
/**
* 需求:利用反射机制操作数组
*/
//创建String类型的数组
String[] ss = (String[]) Array.newInstance(String.class,5);
System.out.println("利用反射来获取数组长度:" + Array.getLength(ss));
//利用反射设置数组元素
Array.set(ss,0,"张三");
Array.set(ss,1,"李四");
Array.set(ss,2,"王五");
Array.set(ss,3,"赵六");
Array.set(ss,4,"虞姬");
//利用反射遍历数组元素
for (int i = 0; i < Array.getLength(ss); i++) {
System.out.println(Array.get(ss,i));
}
}
反射-操作泛型
public static void main(String[] args) throws Exception {
/**
* 需求:利用反射机制操作泛型
*/
//获取Test06的字节码文件对象
Class<?> c = Class.forName("com.dream.reflex01.Test06");
//获取method01的方法对象
Method method01 = c.getMethod("method01", ArrayList.class, HashMap.class);
method01.setAccessible(true);
Type[] genericParameterTypes = method01.getGenericParameterTypes();//获取参数类型
for (Type t : genericParameterTypes) {
ParameterizedType type = (ParameterizedType) t;
//获取参数的泛型的类型
Type[] actualTypeArguments = type.getActualTypeArguments();
for (Type typeArgument : actualTypeArguments) {
System.out.println(typeArgument);
}
}
System.out.println("-----------");
//获取method02方法对象
Method method02 = c.getMethod("method02");
method02.setAccessible(true);
Type genericReturnType = method02.getGenericReturnType();
ParameterizedType parameterizedType = (ParameterizedType) genericReturnType;
//获取返回值的泛型类型
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for (Type type : actualTypeArguments) {
System.out.println(type);
}
}
public static void method01(ArrayList<String> list, HashMap<String,Integer> map){
}
public static HashMap<String,Integer> method02(){
return null;
}
案例
业务与逻辑分离的思想
测试类
public class Test01 {
/**
* 需求: 业务与逻辑分离的思想
*/
public static void main(String[] args) throws Exception {
Scanner scan = new Scanner(System.in);
printName();
System.out.println("请选择数据源:");
int num = scan.nextInt();
DataSource dataSource = getDataSource(num);
dataSource.getData();
scan.close();
}
public static DataSource getDataSource(int num) throws Exception {
Properties p = new Properties();
p.load(Test01.class.getClassLoader().getResourceAsStream("DSClassPath.properties"));
String classPath = p.getProperty("classPath");
String[] split = classPath.split(",");
//根据路径创建对象
Class<?> c = Class.forName(split[num - 1]);
DataSource dataSource = (DataSource) c.newInstance();
return dataSource;
}
public static void printName() throws Exception {
Properties p = new Properties();
p.load(Test01.class.getClassLoader().getResourceAsStream("DSName.properties"));
String name = p.getProperty("name");
String[] split = name.split(",");
StringBuffer sb = new StringBuffer();
int num = 1;
for (String s : split) {
sb.append(num);
sb.append("-");
sb.append(s);
sb.append(" ");
num++;
}
System.out.println(sb);
}
}
抽象类
public abstract class DataSource {
public abstract void getData();
}
数据类
public class LocalDataSource extends DataSource {
@Override
public void getData() {
System.out.println("获取本地数据...");
}
}
public class NetworkDataSource extends DataSource {
@Override
public void getData() {
System.out.println("获取网络数据...");
}
}
public class OtherDataSource extends DataSource{
@Override
public void getData() {
System.out.println("其他数据...");
}
}
反射 + 注解
测试类
public class Test01 {
public static void main(String[] args) {
/**
* 知识点:反射 + 注解 的案例
*/
Student stu = new Student("张三", '男', 21);
//获取类上的注解数据
Class<?> c = stu.getClass();
TableInfo annotation = c.getAnnotation(TableInfo.class);
String tableName = annotation.tableName();
System.out.println(tableName);
//获取属性上的注解数据
Field[] declaredFields = c.getDeclaredFields();
for (Field field : declaredFields) {
FieldInfo fieldInfo = field.getAnnotation(FieldInfo.class);
String name = fieldInfo.name();
String type = fieldInfo.type();
int length = fieldInfo.length();
System.out.println(name + "--" + type + "--" + length);
}
}
}
自定义注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableInfo {
String tableName();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldInfo {
String name();
String type();
int length();
}
学生类
@TableInfo(tableName = "db_student")
public class Student{
@FieldInfo(name = "stu_name",type = "varchar",length = 32)
private String name;
@FieldInfo(name = "stu_sex",type = "varchar",length = 32)
private char sex;
@FieldInfo(name = "stu_age",type = "int",length = 3)
private int age;
public Student() {
}
public Student(String name, char sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void eat() {
System.out.println(this.name + "吃饭饭");
sleep();
}
private void sleep() {
System.out.println(this.name + "睡觉觉");
}
@Override
public String toString() {
return name + "\t" + sex + "\t" + age;
}
}