1.Annotation的作用:
(1).不是程序本身,可以对程序做出解释
(2)."可以被其他程序(编译器)读取"
2.Annotation的格式:
(1).注解是以"@注释名"在代码中存在的,还可以添加一些参数值
3.Annotation在哪里?
(1).可以附加在package,class,method,field等上面,相当于给他们添加
了额外的辅助信息,我们可以通过反射机制编程实现对这些元素数据的访问
@Override :
(1).定义在java.lang.Override 中,此注释只适用于修饰方法,表示一个方法
声明打算"重写"超类中的另一个方法声明:
(2).@ Deprecated: 定义在 java.lang,Deprecated中,此注释可以用于修饰方法
,属性,类,表示不鼓励程序员这样的元素,通常是因为它很危险或则存在更好的
选择。
(3).@SuppressWarnings :定义在java.lang.SuppressWarning中,用来抑制编译时
的警告信息,
Override 重写的注解 (推翻)


Deprecated 不推荐程序员使用,但是可以使用,或则存在更好的方式 (已弃用)


SuppressWarnings("all") 镇压警告 (压制警告)


元注解的作用就是"负责注解其他注解",Java定义了4个标准的meta-annotation类型,
它们被用来提供对其他annotation类型作说明
(1).@Target (目标)
用于描述注解的适用范围(即:被描述的注解可以用在什么地方)
(2).@Retention (保持)
表示需要在什么级别保存该注释信息,用于描述注解的生命周期
(3).@Document (文档)
说明该注解被包含在javadoc中
(4).@inherited (继承)
说明子类可以继承父类中的该注解
@Target (目标) 表示我们的注解可以用在哪些地方

Retention 表示我们的注解在什么地方还有效?
Documented 表示是否将我们的注解生成在JavaDoc
Inherited子类可以继承父类的注解

1.自定义注解定义的方法:
@interface自定义注解时,自动继承了java.lang.annoyation.Annotation的接口
分析:
(1).@interface用来声明一个注解
eg: public @interface 注解名{定义内容}
(2).其中的每一个方法实际上是声明了一个配置参数
(3).方法的名称就是参数的名称
(4).返回值类型就是参数的类型(返回值只能是基本类型, class String enum)
(4).可以同过default来声明参数的默认值
(6).如果只有一个参数成员,一般参数名为value
(7).注解元素必须有值,我们定义注解元素时,经常使用空字符串,0作为默认值
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public class Demo4 {
//注解可以显示赋值,如果没有默认值,我们必须就给注解赋值
@MyAnnotation(name = "吉士先生")
public void test(){
}
@MyAnnotation2("李明")
public void test2(){
}
}
@Target(value = {ElementType.TYPE,ElementType.METHOD}) //适用范围
@Retention(value = RetentionPolicy.RUNTIME) //在什么时候还有效
@interface MyAnnotation{
//注解的参数:参数类型+参数名() 设置了默认值
String name() ;
int age() default 0;
int id() default -1; //如果默认值为-1,代表不存在
String [] string() default {"西部开源","北大"};
}
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
String value(); //如果只有一个值,可以写成value 这么就可以省略一个value
}
1.注解的参数: 参数类型+参数名()
如果没有添加默认值,那么必须在上面的注解中进行赋值

2.注解的参数加一个默认值, 参数类型+参数名() default 默认值
可以不用在注释上赋值了

3.如果注解中只有一个方法:可以把方法名定义成 value() ,那么就可以在
注解上少写一个 value=;

1.静态语言:
是一类与动态语言相对的,"运行的时候不可以改变的语言就是静态语言" java不是
动态语言,但是java可以称之为"准动态语言" ----->反射机制
eg: java c c++
2.动态语言:
是一类在"运行时可以改变其结构的语言",比如新的代码、函数、对象可以引入。
eg: JavaScript
1.Reflection(反射)是java被视为动态语言的关键,反射机制允许程序在执行
期借助于Reflection API获取任何类的内部信息,并且能直接操作任意对象的
内部属性及方法.
"class c=Class.forName("java.lang.String")"
2.加载完类之后,在堆内存的方法区中就产生了一个class类型的对象(一个类只有
一个class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象
看到类的结构。"这个对象就像一面镜子,通过这个镜子看到类的结构,我们称之为"
"反射"
java反射机制提供的功能
1.在运行时判断任意一个对象所属的类
2.在运行时构造任意一个类的对象
3.在运行的时候判断任意一个类的所具有的成员变量和方法
4.在运行时获取泛型信息
5.在运行时调用任意一个对象的成员变量和方法
6.在运行时处理注解
7.生成动态代理
.....
优点:
1.可以实现动态创建对象和编译,体现出很大的灵活性
缺点:
对性能有影响:使用反射基本上是一种解释操作。
通过反射获取对象:
1.
"class c=Class.forName("java.lang.String")"
"并且对象有且只有一个 (就是只有一个值)"
一个类被加载后,类的整个结构都会被封装在class对象中
2.
Class c=person.getClass()
package com.Kuang.reflectiom;
public class Demo5 {
public static void main(String[] args) throws ClassCastException {
//通过反射获取类的class对象
try {
Class aClass_one = Class.forName("com.Kuang.reflectiom.User");
System.out.println(aClass_one);
//一个类在内存中只有一个class对象
//一个类被加载后,类的整个结构都会被封装在class对象中
Class aClass_2 = Class.forName("com.Kuang.reflectiom.User");
Class aClass_3 = Class.forName("com.Kuang.reflectiom.User");
Class aClass_4 = Class.forName("com.Kuang.reflectiom.User");
System.out.println(aClass_2.hashCode());
System.out.println(aClass_3.hashCode());
System.out.println(aClass_4.hashCode());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
//实体类 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;
}
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;
}
}

反射: 通过class对象得出来类
非反射: 通过类得出来对象
1.对象通过反射可以得到的信息:
(1).类的属性
(2).方法
(3).构造器。
2.详解:
(1).class 本身也是一个类
(2).class 对象只能由系统建立对象
(3).一个加载的类在jvm中只会有一个class实列
(4).每个类的实列都会记得自己是由哪个class实列所生成的
(5).通过class可以完整的得到一个类中的所有被加载的结构
(6).class是reflection的根源,针对任何你想动态加载、运行的类,唯有先
获得相应的class对象
(7).一个class对象对应的是一个加载到jvm中的一个class文件
方式1: 通过对象获得
Class c1=person.getClass();
方式2: forName获得
Class<?> aClass = Class.forName("com.Kuang.reflectiom.Student");
方式3:通过类名.class获得
Class studentClass = Student.class;
package com.Kuang.reflectiom;
public class Demo6 {
public static void main(String[] args) {
Person person=new Student();
System.out.println("这个人是:"+person.name);
//方式1: 通过对象获得
Class c1=person.getClass();
System.out.println(c1.hashCode());
//方式2: forName获得
try {
Class<?> aClass = Class.forName("com.Kuang.reflectiom.Student");
System.out.println(aClass.hashCode());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//方式3:通过类名.class获得
Class studentClass = Student.class;
System.out.println(studentClass.hashCode());
Class superclass = c1.getSuperclass(); //得到父类
System.out.println(superclass);
}
}
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对象,就是说一个类型不管数据怎么变化
class对象是不会变的。
package com.Kuang.reflectiom;
import java.lang.annotation.ElementType;
public class Demo7 {
public static void main(String[] args) {
Class c1 = Object.class;
Class c2=Comparable.class; //接口
Class c3=String[].class; //一维数组
Class c4=int[][].class; //二维数组
Class c5=Override.class; //注解
Class c6= ElementType.class; //枚举
Class c7=Integer.class; //基本数据类型
Class c8=void.class; //空型
Class c9=Class.class; //Class型
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println(c5);
System.out.println(c6);
System.out.println(c7);
System.out.println(c8);
System.out.println(c9);
}
}

java的内存分析:

类的加载过程:

类的加载与classLoader的理解

package com.Kuang.reflectiom;
public class Demo8 {
public static void main(String[] args) {
A s=new A();
System.out.println(A.m);
}
}
class A{
static {
System.out.println("A 类静态代码初始化");
m=300;
}
static int m=100;
public A(){
System.out.println("A 类的无参构造初始化");
}
}

什么时候会发生类初始化?
1.类的主动引用(一定会发生类的初始化)
(1).当虚拟机启动,先初始化main方法所在的类
(2).new 一个类的对象
(3).调用类的静态成员(除了final常量)和静态方法
(4).使用reflect 的方法进行反射调用
(5).当初始化一个类,如果其父类没有被初始化,则先会初始化它的父类
"(意思就是:当我们new子类的对象的时候,父类的构造器会被先初始化)"
2.类的被动引用(不会发生类的初始化)
(1).当访问一个静态域时,只有真正声明这个域得类才会被初始化,
(2).通过数组定义类引用,不会触发此类的初始化
(3).引用常量不会触发此类的初始化
当初始化一个类,如果其父类没有被初始化,则先会初始化它的父类
package com.Kuang.reflectiom;
public class Demo9 {
static {
System.out.println("main类被加载!");
}
public static void main(String[] args) {
//Son son=new Son();
//利用反射的方法
try {
Class.forName("com.Kuang.reflectiom.Son");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
class Father{
static int b=2;
static {
System.out.println("父类被加载");
}
}
class Son extends Father{
static {
System.out.println("子类被加载");
m=300;
}
static int m=100;
static final int M=1;
}

1.类加载器的作用:
将class文件字节码内容加载到内存中,并将这些静态数据转换成方法去的运行时
数据结构,然后在堆中生成一个戴白哦这个类的class对象,作为方法区中类数据
的访问入口
2.java文件过程:
java文件--->java编译器---->字节码(.class文件)---->类装载器
----->字节码校验器----->解释器----->操作系统平台
3.类加载器的作用:
类加载器的作用是用来把类(class)装载进内存的,jvm规范定义了如下的加载器:
(1).引导类加载器: jvm自带的加载器,"负责java平台核心库"。该加载器无法直
接获取.
(2).扩展类加载器: 负责jre/lib/ext目录库下的jar包
(3).系统加载器:负责classpath或path所指目录下的jar包
package com.Kuang.reflectiom;
public class Demo10 {
public static void main(String[] args) {
//获取系统类的加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
//获取系统类的加载器的父类加载器---->扩展类加载器
ClassLoader parent = systemClassLoader.getParent();
System.out.println(parent);
//获取扩展类加载器的父类 ---->跟加载器
ClassLoader parent1 = parent.getParent();
System.out.println(parent1);
//当前类是那个加载器加载的?
try {
ClassLoader classLoader = Class.forName("com.Kuang.reflectiom.Demo7").getClassLoader();
System.out.println(classLoader);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}

1.获得包名+类名
System.out.println(aClass.getName());
2.获得类名
System.out.println(aClass.getSimpleName());
3.获得类的全部属性
aClass.getDeclaredFields()
4.获得类的public属性
aClass.getField();
5.获得本类的及父类的全部public方法
aClass.getMethods();
6.获得类的所有方法
aClass.getDeclaredMethods();
7.获得类的指定方法:
aClass.getMethod();
7.获得全部构造器:
aClass.getDeclaredConstructors();
package com.Kuang.reflectiom;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Demo11 {
public static void main(String[] args) {
try {
Class<?> aClass = Class.forName("com.Kuang.reflectiom.User");
//获得类的名字
System.out.println(aClass.getName()); //获得包名+类名
System.out.println(aClass.getSimpleName()); //获得类名
//获得类的属性
Field[] fields=aClass.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("------------------");
//获得类的方法
Method[] declaredMethods = aClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}

1.
创建类的对象: 调用class对象的newInstance()方法
(1).类必须有一个无参数的构造器
(2).类的构造器的访问权限需要足够
eg: User user = (User) aClass.newInstance(); 构造一个对象----->本质上调用了无参
2.难道没有无参的构造器就不能创建对象了么?
(1).只要在操作的时候明确的调用类中的构造器,并将参数传递进去之后,
才可以实列化.
2.没有无参构造器的解决办法:
这里User没有添加: 无参
package com.Kuang.reflectiom;
public class Demo5 {
public static void main(String[] args) throws ClassCastException {
//通过反射获取类的class对象
try {
Class aClass_one = Class.forName("com.Kuang.reflectiom.User");
System.out.println(aClass_one);
//一个类在内存中只有一个class对象
//一个类被加载后,类的整个结构都会被封装在class对象中
Class aClass_2 = Class.forName("com.Kuang.reflectiom.User");
Class aClass_3 = Class.forName("com.Kuang.reflectiom.User");
Class aClass_4 = Class.forName("com.Kuang.reflectiom.User");
System.out.println(aClass_2.hashCode());
System.out.println(aClass_3.hashCode());
System.out.println(aClass_4.hashCode());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
//实体类 pojo,entity
class User{
private String name;
private int id;
private int age;
public User(String name, int id, int age) {
this.name = name;
this.id = id;
this.age = age;
}
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 +
'}';
}
}
package com.Kuang.reflectiom;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Demo12 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//获得class对象
Class aClass = Class.forName("com.Kuang.reflectiom.User");
//获得构造器 ,通过构造器创建对象----->调用了有参
Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class, int.class, int.class);
User user2 = (User)declaredConstructor.newInstance("吉士先生", 001, 18);
System.out.println(user2);
}
}
1.执行方法:
setAccessible(true); 关闭权限检测
invoke(user3,"吉士先生") invoke: 激活的意思 (对象,"方法的值")
package com.Kuang.reflectiom;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Demo12 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//获得class对象
Class aClass = Class.forName("com.Kuang.reflectiom.User");
//构造一个对象----->调用了无参
User user = (User) aClass.newInstance();
System.out.println(user);
//获得构造器 ,通过构造器创建对象----->调用了有参
Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class, int.class, int.class);
User user2 = (User)declaredConstructor.newInstance("吉士先生", 001, 18);
System.out.println(user2);
//通过反射调用方法
User user3=(User) aClass.newInstance();
Method setName = aClass.getDeclaredMethod("setName", String.class);
//invoke: 激活的意思 (对象,"方法的值")
setName.invoke(user3,"吉士先生");
System.out.println(user3.getName());
//通过反射操作属性
User user4=(User) aClass.newInstance();
Field name = aClass.getDeclaredField("name");
name.setAccessible(true); //关闭权限检测,如果不关闭,那么私有属性我们就访问不了
name.set(user4,"吉士先生2");
System.out.println(user4.getName());
}
}

1.java采用泛型擦除的机制来引入泛型,java中的泛型仅仅是给编译器javac使用的,
确保数据的安全性和免去强制类型转换问题,但是,一旦编译完成,所有和泛型有关
的类型全部擦除。
2.为了通过反射操作这些类型,java新增了parameterizedTpye,GenericType,
TypeVaiable和WildcardType几种类型来代表不能被归一到class类中的类型但是
又和原始类型齐名的类型
(1).parameterizedTpye: 表示一种参数化类型
(2).GenericType: 表示一种元素类型是参数化类型或者类型变量的数组类型
(3).TypeVaiable: 是各种类型变量的公共父接口
(4).WildcardType: 代表一种通配符类型表达式。
package com.Kuang.reflectiom;
import java.lang.annotation.*;
import java.lang.reflect.Field;
public class Demo13 {
public static void main(String[] args) throws NoSuchFieldException {
try {
Class<?> aClass = Class.forName("com.Kuang.reflectiom.Student2");
//通过反射获得注解
Annotation[] annotations = aClass.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//获得注解的value的值
TableKuang tableKuang = (TableKuang) aClass.getAnnotation(TableKuang.class);
String value = tableKuang.value();
System.out.println(value);
//获得类指定的注解
Field name = aClass.getDeclaredField("name");
FieldKuang annotation = name.getAnnotation(FieldKuang.class);
System.out.println(annotation.columname());
System.out.println(annotation.type());
System.out.println(annotation.length());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
@TableKuang("db_student")
class Student2{
@FieldKuang(columname = "db_id",type = "int",length = 10)
private int id;
@FieldKuang(columname = "db_age",type = "int",length = 10)
private int age;
@FieldKuang(columname = "db_name",type = "Varchar",length = 10)
private String name;
public Student2() {
}
public Student2(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "com.Kuang.reflectiom.Student2{" +
"id=" + id +
", age=" + age +
", 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;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableKuang{
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldKuang{
String columname();
String type();
int length();
}