注解是JDK5.0引入的新技术。注解不是程序本身,但可以对程序做出解释。且可以被其他程序(如:编译器)读取。
注解的格式是 “@注释名”。还可以添加一些数值,如抑制警告,@SuppressWarnings(value=“unchecked”) 。
注解可分为:内置注解,元注解,自定义注解。
public class testAnnotation extends Object {
//重写方法
@Override
public String toString(){
return super.toString();
}
//不推荐程序员使用,但是可以使用,或者存在更好的方法
@Deprecated
public static void test(){
System.out.println("Deprecated");
}
public void test1(){
}
}
@MyMetaAnnotation
public class testMetaAnnotation {
public void test(){
}
}
//定义一个注解
@interface MyAnnotation{
}
//定义一个元注解
//Target用于描述注解的使用范围(被描述的注解可以用在什么地方)
@Target(value = {ElementType.METHOD,ElementType.TYPE})
//Retention表示我们的注解在什么地方还有效
@Retention(value = RetentionPolicy.RUNTIME)
//Documented表示是否将我们的注解生成在JAVAdoc中
@Documented
//Inherited说明子类可以继承父类中的该注解
@Inherited
@interface MyMetaAnnotation{
}
自定义注解:使用@interface 注解名,自定义一个注解,自动继承java.lang.annotation.Annotation接口
这里的RetentionPolicy value();方法,实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值的类型就是参数的类型(返回值只能是基本类型,Class,String,enum)。可以通过default来声明参数的默认值,如果只有一个参数成员,一般参数名为value,注解元素必须有值,定义注解元素时,经常用(空字符串,0)作为默认值。
public class tesDefineAnnotation {
//注解可以显示赋值,如果没有默认值必须赋值
@MyAnnotation2(name = "yang", age = 20, id = 1234, schools = "家里蹲")
public void test(){}
@MyAnnotation3("yang")
public void test1(){}
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
//注解的参数:参数类型+参数名();
//default "" 默认为空
String name() default "";
int age() default 0;
int id() default -1;//如果默认值为-1,代表不存在
String[] schools() default {"清华"};
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
//只有一个参数,且为默认名称value时,添加注解时可以省略value=,其他名称不行
String value();
}
动态语言:在运行时可以改变其结构的语言,如Object-C,C#,JavaScript,PHP,Python等。静态语言:运行时结构不可变的语言,如Java,C,C++。Java作为静态语言,因为反射机制拥有了动态性。
反射机制允许程序在执行期间借助于Reflection API获取任何类的内部信息。
简单的反射案例
public class testReflection {
public static void main(String[] args) throws ClassNotFoundException {
//通过反射获取类的Class对象
Class c=Class.forName("com.yang.learning.AnnotationAndReflection.User");
System.out.println(c);
Class c1=Class.forName("com.yang.learning.AnnotationAndReflection.User");
Class c2=Class.forName("com.yang.learning.AnnotationAndReflection.User");
//一个类在内存中只有一个Class对象
//一个类被加载后,类的整个结构都会被封装在Class对象中
System.out.println(c1.hashCode());
System.out.println(c2.hashCode());
}
}
//实体类pojo,entity
class User{
private String name;
private int id;
private int age;
public User(){}
public User(String name, int id, int age) {
this.name = name;
this.id = id;
this.age = age;
}
private void test(){}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", id=" + id +
", age=" + age +
'}';
}
}
优点:可以实现动态创建对象和编译,体现出很大的灵活性
缺点:对性能有影响
具体代码如下:
public class testClassMethod {
public static void main(String[] args) throws ClassNotFoundException {
Person person=new Student();
System.out.println("这个人是:"+person.name);
//方式一:通过对象获得
Class c1=person.getClass();
System.out.println(c1.hashCode());
//方式二:forname获得
Class c2=Class.forName("com.yang.learning.AnnotationAndReflection.Student");
System.out.println(c2.hashCode());
//方式三:通过类名.class获得
Class c3=Student.class;
System.out.println(c3.hashCode());
//方式四:基本内置类型的包装类都有一个Type属性
Class c4=Integer.TYPE;
System.out.println(c4);
//获得父类类型
Class c5=c1.getSuperclass();
System.out.println(c5);
}
}
class Person{
public String name;
public Person() {
}
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
class Student extends Person{
public Student() {
this.name="学生";
}
}
class Teacher extends Person{
public Teacher() {
this.name="老师";
}
}
通过反射获取Class对象后,我们能做什么?
public class testGetClassInformation {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1=Class.forName("com.yang.learning.AnnotationAndReflection.User");
//获得类的名字
System.out.println(c1.getName()); //获得包名+类名
System.out.println(c1.getSimpleName()); //获得类名
//获得类的属性
System.out.println("=================================");
Field[] fields = c1.getFields(); //只能找到public属性
// for(Field field:fields){
// System.out.println(field);
// }
fields = c1.getDeclaredFields(); //可以找到全部属性
for(Field field:fields){
System.out.println(field);
}
//获得指定属性的值
Field name = c1.getDeclaredField("name");
System.out.println(name);
System.out.println("=================================");
//获得类的方法
Method[] methods = c1.getMethods(); //获得本类及其父类的全部public方法
for (Method method:methods){
System.out.println("正常的:"+method);
}
methods=c1.getDeclaredMethods(); //获得本类的全部方法
for (Method method:methods){
System.out.println("getDeclaredMethods:"+method);
}
//获得指定方法
Method getName=c1.getMethod("getName",null);
Method setName=c1.getMethod("setName",String.class);
System.out.println(getName);
System.out.println(setName);
System.out.println("=================================");
//获得指定的构造器
Constructor[] constructors = c1.getConstructors();
for(Constructor constructor:constructors){
System.out.println(constructor);
}
constructors=c1.getDeclaredConstructors();
for(Constructor constructor:constructors){
System.out.println("##"+constructor);
}
//获得指定构造器
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
System.out.println(declaredConstructor);
}
}
**public class testReflectionCreateObject {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//获得class对象
Class c1=Class.forName("com.yang.learning.AnnotationAndReflection.User");
//构造一个对象
// User user=(User) c1.newInstance(); //本质上是调用类的无参构造
// System.out.println(user);
//通过构造器创建对象
// Constructor constructor = c1.getConstructor(String.class, int.class, int.class);
// User user2 = (User) constructor.newInstance("yang", 123, 18);
// System.out.println(user2.toString());
//通过反射调用普通方法
User user3 =(User) c1.newInstance();
//通过反射操作方法
Method setName = c1.getDeclaredMethod("setName", String.class);
//invoke激活
//(对象,”方法的值“)
setName.invoke(user3,"yang");
System.out.println(user3.getName());
//通过反射操作属性
System.out.println("========================");
User user4 =(User) c1.newInstance();
Field name= c1.getDeclaredField("name");
//不能直接操作私有属性,需要关闭程序的安全检测,属性或者方法的setAccessible(true)
name.setAccessible(true);
name.set(user4,"yang1");
System.out.println(user4.getName());
}
}**
Java使用的是泛型擦除机制来引入泛型,Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换问题,但是,一旦编译完成,所有和泛型有关的类型全部擦除。
Java新增了ParameterizedType,GenericArrayType,TypeVariable,WildcardType几种类型来代表不能被归一到Class类中的类型,但是有何原始类型齐名的类型
public class testGenerics {
public void test1(Map<String ,User> map, List<User> list){
System.out.println("test1");
}
public Map<String ,User> test2(){
System.out.println("test2");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Method method = testGenerics.class.getMethod("test1", Map.class, List.class);
Type[] genericParameterTypes = method.getGenericParameterTypes(); //获取泛型的参数类型
for(Type genericParameterType:genericParameterTypes){
System.out.println("#"+genericParameterType);
if (genericParameterType instanceof ParameterizedType){ //获得的参数类型是否等于结构化的参数类型
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for(Type actualTypeArgument:actualTypeArguments){
System.out.println(actualTypeArgument);
}
}
}
method = testGenerics.class.getMethod("test2", null);
Type genericReturnType = method.getGenericReturnType();
if (genericReturnType instanceof ParameterizedType){ //获得的参数类型是否等于结构化的参数类型
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for(Type actualTypeArgument:actualTypeArguments){
System.out.println(actualTypeArgument);
}
}
}
}
public class testReflectionOAnnotation {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.yang.learning.AnnotationAndReflection.Student2");
//通过反射获得类的注解
Annotation[] annotations = c1.getAnnotations();
for(Annotation annotation:annotations){
System.out.println(annotation);
}
//获得类的注解的value的值
Tableyang Tyang = (Tableyang) c1.getAnnotation(Tableyang.class);
String value=Tyang.value();
System.out.println(value);
//获得类指定的注解
Field f = c1.getDeclaredField("name");
Fieldyang annotation = f.getAnnotation(Fieldyang.class);
System.out.println(annotation.columnName());
System.out.println(annotation.type());
System.out.println(annotation.length());
}
}
@Tableyang("db_student")
class Student2{
@Fieldyang(columnName = "db_age",type = "int",length = 10)
private int age;
@Fieldyang(columnName = "db_id",type = "int",length = 10)
private int id;
@Fieldyang(columnName = "db_name",type = "String",length = 3)
private String name;
public Student2() {
}
public Student2(int age, int id, String name) {
this.age = age;
this.id = id;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student2{" +
"age=" + age +
", id=" + id +
", name='" + name + '\'' +
'}';
}
}
//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Tableyang{
String value();
}
//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Fieldyang{
String columnName();
String type();
int length();
}