类的加载:

  当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载、连接、初始化这三个步骤来实现对这个类进行初始化。

  加载:

    就是指将class文件加载进入内存,并为之创建一个Class对象

    任何类被使用时,系统都会创建一个Class对象

  连接:

    验证: 是否有正确的内部结构,并且和其他类协调一致

    准备: 负责为类的静态成员分配内存,并设置默认初始化值

    解析: 将类的二进制数据中的符号引用替换为直接引用

  初始化:就是以前我们讲过的初始化步骤

类初始化的时机:

  创建类的实例

  访问类的静态方法或者为类的静态变量赋值

  使用反射机制来强制创建某个类或接口对应的java.lang.Class对象

  初始化某个类的子类

  直接使用java.exe命令来运行某个主类

类加载器

  类加载器

    负责将文件加载到内存中。并为之生成对应的Class对象

    虽然我们不需要关系类加载器原理,但是了解这个机制有利于我们更好的理解程序的运行

  类加载器的分类

    Bootstrap ClassLoader(根类加载器)

      也被称为引导加载器,负责java核心类的加载

        比如System、String等。在JDK中JRE的rt.jar中

    Extension ClassLoader(扩展类加载器)

      负责JRE的扩展目录中的jar包的加载

         在JDK中JRE中lib下的ext目录下

    System ClassLoader(系统类加载器)

      负责在JVM启动时加载来自java命令的class文件以及在classpath环境变量所指定的jar包和类路径

反射:

生成class对象:

package com.gz_01;

/*
* 发射:通过class文件对象,使用该文件中的成员变量,构造方法,成员方法
*
* Person p=new Person();
* p.使用
*
* 使用反射使用对应类中的方法,必须先的到该Class的文件对象,也就是得到Class类的对象
* Class类:
* 成员变量 Field
* 构造方法 Constructor
* 成员方法 Method
*
* 得到Class对象,三种方式:
* 一个类的Class对象表示该类对应的Class文本对象。所以同一个类的Class类是相同的。在类元素前后不改变的情况下
* 1、 Class<?> getClass() 返回此 Object 的运行时类。
* 2、class 数据类型的静态方法
* 3、static Class<?> forName(String className) 返回与带有给定字符串名的类或接口相关联的 Class 对象。
*
* 一般使用什么方法得到class对象呢?
* 自己玩:随便用,类名.class.最方便
* 开发:Class.forName(String className)
* 为什么呢?因为开发中往往别人给你的是jar文件,所以使用对象.getClass可能行不通。不同人的类名可能相同,第二种方式也可能出问题,并且第三种方式还可以配置在配置文件中
*
* */
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
// 方式1:
Person p=new Person();
Class c1=p.getClass();
// Person p2=new Person();
// Class c2=p2.getClass(); // 方式2:
Class c2=Person.class;
// System.out.println(p==p2); // 方式3:
//java.lang.ClassNotFoundException //这里填写的是类名的全路径。如何正确书写类的全路径呢?
//1、在外面一步一步从报名.子包名...类名,一步一步走过去
//右键copy Qualified name
Class c3=Class.forName("com.gz_01.Person");
System.out.println(c1==c3);
}
}
package com.gz_01;

public class Person {
private String name;
int age;
public String address; public Person(){ }
private Person(String name){
this.name=name;
}
public Person(String name,int age,String address){
this.name=name;
this.age=age;
this.address=address;
} public void show(){
System.out.println("show");
} void method(String name,String address){
System.out.println(name+"---"+address);
}
private String function(){
return name+"---"+age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", address=" + address
+ "]";
} }

Person.java

利用class对象得到构造:

package com.gz_02;

import java.lang.reflect.Constructor;

public class RefelectDemo01 {
public static void main(String[] args) throws Exception {
//得到反射的Class对象
Class c=Class.forName("com.gz_01.Person"); //我们希望通过该字节码对象使用该类的方法,所以我们如何生成该类的对象呢?构造方法
// Constructor getConstructor(Class... parameterTypes) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定 公共构造 方法。
// Constructor[] getConstructors() 返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。
// Constructor getDeclaredConstructor(Class... parameterTypes) 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。
//Constructor[] getDeclaredConstructors() 返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。 // Constructor[] cor=c.getConstructors();//获取所有公共构造
// Constructor[] cor=c.getDeclaredConstructors();//获取所有构造
// for(Constructor cc:cor){
// System.out.println(cc);
// }
Constructor cor=c.getConstructor();//获取指定构造 注意参数是类型Class文件的可变参
//Constructor的方法
// T newInstance(Object... initargs) 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
Object o=cor.newInstance();
System.out.println(o);
//做了上面这么多,相当于实现了这样一个功能
//Object o=new Person();
} }
package com.gz_02; import java.lang.reflect.Constructor; //使用带参构造
//public Person(String name,int age,String address)
public class RefelectDemo02 {
public static void main(String[] args) throws Exception { Class c=Class.forName("com.gz_01.Person"); Constructor cor=c.getConstructor(String.class,int.class,String.class); Object o=cor.newInstance("林青霞",27,"北京");
System.out.println(o);
}
}
package com.gz_02; import java.lang.reflect.Constructor; //获取私有构造方法并使用
//private Person(String name)
public class RelectDemo03 {
public static void main(String[] args) throws Exception {
// Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。
Class c=Class.forName("com.gz_01.Person"); Constructor cor=c.getDeclaredConstructor(String.class); //IllegalAccessException 非法的访问异常 不能访问private修饰的 //public void setAccessible(boolean flag)将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查。
cor.setAccessible(true);//解除该对象的java访问检查
Object o=cor.newInstance("刘亦菲"); System.out.println(o);
}
}

利用class对象得到成员变量:

package com.gz_03;

import java.lang.reflect.Field;

//需求:通过反射获取成员变量并使用
public class RefelcetDemo {
public static void main(String[] args) throws Exception { Class c=Class.forName("com.gz_01.Person");
// Field getDeclaredField(String name)
// 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
// Field[] getDeclaredFields()
// 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。
// Field getField(String name)
// 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
// Field[] getFields()
// 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
// Field[] ff=c.getFields();//public java.lang.String com.gz_01.Person.address
// Field[] ff=c.getDeclaredFields();//private java.lang.String com.gz_01.Person.name int com.gz_01.Person.age public java.lang.String com.gz_01.Person.address
// for(Field f:ff){
// System.out.println(f);
// } // /Field f=c.getField("name");//java.lang.NoSuchFieldException
// Field f=c.getField("address");
Field addressField=c.getDeclaredField("address");
// System.out.println(addressField);
//void set(Object obj, Object value) 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。 //先新建一个对象,才能配合set方法使用
Object o=c.getConstructor().newInstance();
// System.out.println(o);
addressField.set(o, "北京");
System.out.println(o); //给name赋值private String name;
Field nameField=c.getDeclaredField("name");
// System.out.println(o);
//java.lang.IllegalAccessException
nameField.setAccessible(true);//去除java访问检查
nameField.set(o, "林青霞");
System.out.println(o); //给age赋值int age;
Field ageField=c.getDeclaredField("age");
//java.lang.IllegalAccessException
ageField.setAccessible(true);
ageField.setInt(o, 27);
System.out.println(o); }
}

利用class对象得到成员方法:

package com.gz_04;

import java.lang.reflect.Method;

//通过反射获取成员方法并使用
public class RefelectDemo {
public static void main(String[] args) throws Exception { Class c=Class.forName("com.gz_01.Person");
// Method getDeclaredMethod(String name, Class<?>... parameterTypes)
// 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。
// Method[] getDeclaredMethods()
// 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
// Method getEnclosingMethod()
// 如果此 Class 对象表示某一方法中的一个本地或匿名类,则返回 Method 对象,它表示底层类的立即封闭方法。
// Method getMethod(String name, Class<?>... parameterTypes)
// 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
// Method[] getMethods()
// 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。
// Method[] ms=c.getMethods();
// Method[] ms=c.getDeclaredMethods();//不包括继承的方法
// for(Method m:ms){
// System.out.println(m);
// }
Method showMethod=c.getMethod("show");
//Object invoke(Object obj, Object... args) 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。 //来一个对象,带个参
Object o=c.getConstructor(String.class,int.class,String.class).newInstance("林青霞",27,"北京"); showMethod.invoke(o); Method functionMethod=c.getDeclaredMethod("function");
//IllegalAccessException
functionMethod.setAccessible(true);
System.out.println(functionMethod.invoke(o)); }
}

使用反射运行配置文件:

package com.gz_05;

import java.io.FileReader;
import java.lang.reflect.Method;
import java.util.Properties; //使用反射运行配置文件
public class Test {
public static void main(String[] args) throws Exception {
// Student s=new Student();
// s.love();
// Teacher t=new Teacher();
// t.Love();
// Worker w=new Worker();
// w.love();
//使用反射,将配置文件放在class.txt里面
Properties prop=new Properties();
FileReader fr=new FileReader("src/class.txt");
prop.load(fr);
String className=prop.getProperty("className");
String methodName=prop.getProperty("methodName"); Class c=Class.forName(className); Object obj=c.getConstructor().newInstance(); Method m=c.getMethod(methodName);
m.invoke(obj); } }
package com.gz_05; public class Student {
public void love(){
System.out.println("爱生活,爱JAJA!");
} }
package com.gz_05; public class Teacher {
private String name;
public void love(){
System.out.println("爱生活,爱青霞!");
}
@Override
public String toString() {
return "Teacher [name=" + name + "]";
} }
package com.gz_05; public class Worker {
public void love(){
System.out.println("爱生活,爱老婆!");
}
} class.txt
className=com.gz_05.Worker
methodName=love

使用反射越过泛型检查:

package com.gz_05;

import java.lang.reflect.Method;
import java.util.ArrayList; //通过反射越过泛型检查
public class ArrayListDemo {
public static void main(String[] args) throws Exception {
ArrayList<Integer> al=new ArrayList<Integer>();
al.add(10);
// al.add("nihao");//报错了
//我们知道,泛型只是编译期的一种检查限制的机制,其实在字节码文件中是不存在泛型的,查看源码,
//我们发现在使用add()的参数是Object,add(10)世纪上是针对10包装成Integer类型然后add进去,通过反射,我们越过强制包装秤Integer
Class c=al.getClass();
Method add=c.getMethod("add", Object.class);
add.invoke(al, "nihao");
System.out.println(al.get(1));
}
}
package com.gz_05; import java.lang.reflect.Field; /*
* 写一个方法
* public void setProperty(Object obj,String propertyName,Object value){}将Object中名propertyName的属性赋值为value
* */
public class Tool {
public static void main(String[] args){
Teacher t=new Teacher();
setProperty(t, "name", "零");
System.out.println(t);
}
public static void setProperty(Object obj,String propertyName,Object value){
Class c=obj.getClass();
try {
Field p=c.getDeclaredField(propertyName);
p.setAccessible(true);
p.set(obj, value);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}

类的加载到反射reflect的更多相关文章

  1. Java程序设计19——类的加载和反射-Part-B

    接下来可以随意提供一个简单的主类,该主类无须编译就可使用上面的CompileClassLoader来运行它. package chapter18; public class Hello { publi ...

  2. Java程序设计19——类的加载和反射-Part-A

    1 本文概要 本章介绍Java类的加载.连接和初始化的深入知识,并重点介绍Java反射相关的内容.本章知识偏底层点,这些运行原理有助于我们更好的把我java程序的运行.而且Java类加载器除了根加载器 ...

  3. 24.类的加载机制和反射.md

    目录 1类的加载连接和初始化 1.1类的加载过程 1.2类的加载器 1.2.1类的加载机制 1类的加载连接和初始化 1.1类的加载过程 类的加载过程简单为分为三步:加载->连接->初始化 ...

  4. 类的加载、时机、反射、模板设计、jdk7/jdk8新特性(二十六)

    1.类的加载概述和加载时机 * A:类的加载概述 * 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. * 加载 * 就是指将class文 ...

  5. java 反射,类的加载过程以及Classloader类加载器

    首先自定义一个类Person package reflection; public class Person { private String name; public int age; public ...

  6. java 27 - 1 反射之 类的加载器

    说到反射,首先说类的加载器. 类的加载: 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. 加载: 就是指将class文件读入内存,并为之 ...

  7. 反射 类的加载 Schema DOM 解析方式和解析器 命名空间

    Day15 反射 1.1 类的加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. l 加载 就是指将class文件读入内存,并为之创建 ...

  8. Java基础_类的加载机制和反射

    类的使用分为三个步骤: 类的加载->类的连接->类的初始化 一.类的加载 当程序运行的时候,系统会首先把我们要使用的Java类加载到内存中.这里加载的是编译后的.class文件 每个类加载 ...

  9. Java反射——java.lang.Class和类的加载

    反射的基础: java.lang.Class Class类的实例对象,用于记录类描述信息. 源码说:represent classes and interfaces in a running Java ...

随机推荐

  1. 将HTMLCollection/NodeList/伪数组转换成数组

    这里把符合以下条件的对象称为伪数组(ArrayLike) 1,具有length属性 2,按索引方式存储数据 3,不具有数组的push,pop等方法 如 1,function内的arguments . ...

  2. HDU 4034 Graph(floyd,最短路,简单)

    题目 一道简单的倒着的floyd. 具体可看代码,代码可简化,你有兴趣可以简化一下,就是把那个Dijsktra所实现的功能放到倒着的floyd里面去. #include<stdio.h> ...

  3. HDU 1393 Weird Clock (英语,纪念题)

    这题简单,只要看懂题目就好,坑爹的是我的英语水平太差了,wa了n次,所以 仅此纪念 一下. //坑爹的英语题目,注意重点:move d times clockwise the current time ...

  4. springmvc web应用程序 java

    搭建普通 springmvc 1.如图建立相关文件 建立在WEB-INF下比较安全,不能直接访问资源. 2.建立Controller控制器,如图 3.需要导入的jar包 commons-logging ...

  5. poj 2480 Longge's problem 积性函数

    思路:首先给出几个结论: 1.gcd(a,b)是积性函数: 2.积性函数的和仍然是积性函数: 3.phi(a^b)=a^b-a^(b-1); 记 f(n)=∑gcd(i,n),n=p1^e1*p2^e ...

  6. HDU4003 Find Metal Mineral 树形DP

    Find Metal Mineral Problem Description Humans have discovered a kind of new metal mineral on Mars wh ...

  7. UITableview刷新某一个cell或section

    //一个section刷新 NSIndexSet *indexSet=[[NSIndexSet alloc]initWithIndex:2]; [tableview reloadSections:in ...

  8. Java学习笔记之:Java 流

    一.介绍 Java.io包几乎包含了所有操作输入.输出需要的类.所有这些流类代表了输入源和输出目标. Java.io包中的流支持很多种格式,比如:基本类型.对象.本地化字符集等等. 一个流可以理解为一 ...

  9. c#实现打印功能,可以设置纸张大小,字体和颜色等

    /// <summary> /// 打印的按钮 /// </summary> /// <param name="sender"></par ...

  10. 文件格式PDF

    pdf(Portable Document Format的简称,意为“便携式文档格式”),是由Adobe Systems用于与应用程序.操作系统.硬件无关的方式进行文件交换所发展出的文件格式.PDF文 ...