1.Class相关知识

  Class类可以理解为类的图纸,通过Class类可以分析类的结构、构建出类的实例。

  Class.forName("test.TestClass").newInstance()方法要求类test.TestClass必须有一个无参的构造函数,否则会报错。

  Class.forName(test.TestClass)会将类test.TestClass加载到JVM中,并完成初始化的工作,类中的静态方法会执行。

  Class c = Class.forName(test.TestClass);中Class.forName方法返回的Class有一些常用的方法返回Class的信息,如下:

package rtti;

import java.util.ArrayList;
import java.util.Arrays; public class ClassInfoTest { public static void main(String[] args) throws InstantiationException, IllegalAccessException {
try {
/*Class clazz = Class.forName("rtti.BenzCar");
System.out.println("simple name: " + clazz.getSimpleName());
System.out.println("canonical name: " + clazz.getCanonicalName());
System.out.println("isInterface: " + clazz.isInterface());
System.out.println("interfaces: " + Arrays.asList(clazz.getInterfaces()));
System.out.println("superclass: " + clazz.getSuperclass());*/ //BenzCar.class与Class.forName("rtti.BenzCar")的不同在于不会直接进行类的初始化,而是等到
// 访问类的静态方法或者成员变量时
Class<? extends BenzCar> clazz = BenzCar.class;
System.out.println("test if have load BenzCar class");
BenzCar car = clazz.newInstance();
System.out.println(car.getPrice()); if(car instanceof BenzCar){
System.out.println("car instanceof BenzCar");
}
if(car instanceof Car){
System.out.println("car instanceof Car");
} if(clazz.isInstance(car)){
System.out.println("car isInstance BenzCar");
} if(Car.class.isInstance(car)){
System.out.println("car isInstance Car");
} System.out.println(ArrayList.class.isAssignableFrom(Object.class)); //false
System.out.println(Object.class.isAssignableFrom(ArrayList.class)); //true } catch (Exception e) {
e.printStackTrace();
}
}
} class Car{}
interface product{} class BenzCar extends Car implements product{
static{
System.out.println("Loading BenzCar class");
} double price = 12000d; public double getPrice(){
return price;
}
}

  输出结果为:

test if have load BenzCar class
Loading BenzCar class
12000.0
car instanceof BenzCar
car instanceof Car
car isInstance BenzCar
car isInstance Car
false
true

  instanceof和isInstance()方法的作用是完全一致的。

2.反射相关知识

  Class类与java.lang.reflect下的各类完成了对反射的支持,主要的类包括Field、Method、Constructor等。

  通过反射我们甚至可以调用类的私有方法,构造出一个甚至多个新的单例模式的实例。

package rtti;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays; public class ReflectTest { public static void main(String[] args) {
Class<?> demo = null;
try{
demo = Class.forName("rtti.Person"); // = Person.class, = Person.getClass()
}catch (Exception e) {
e.printStackTrace();
}
Person per1 = null;
Person per2 = null;
Person per3 = null;
//取得全部的构造函数
Constructor<?> cons[] = demo.getConstructors();
try{
per1 = (Person)cons[0].newInstance();
per2 = (Person)cons[1].newInstance("Rollen",20);
per3 = Person.class.newInstance(); //Person.class.newInstance("Rollen",20); error
}catch(Exception e){
e.printStackTrace();
}
System.out.println(per1);
System.out.println(per2);
System.out.println(per3); System.out.println("interface of which Person Class implements: " + Arrays.asList(Person.class.getInterfaces()));
System.out.println("super class of Person Class: " + Person.class.getSuperclass().getSimpleName());
//获取方法
Method[] methods = Person.class.getDeclaredMethods(); //getMethods() will get superclass's method
for(Method method:methods){
String modifier = Modifier.toString(method.getModifiers());
String returnType = method.getReturnType().getSimpleName();
String methodName = method.getName();
Class [] excepts = method.getExceptionTypes(); Class [] clazzs = method.getParameterTypes();
StringBuffer params = new StringBuffer("");
for(Class clazz:clazzs){
params.append(clazz.getSimpleName()).append(",");
}
String param = "";
if(params.length() > 1){
param = params.substring(0, (params.length()-1));
}
System.out.println(modifier + " " + returnType + " " + methodName + "(" + param + ")" +
" " + (excepts.length == 0 ? "" :"throws " + excepts[0].getSimpleName()));
}
//获取成员变量
Field [] fields = Person.class.getDeclaredFields();
for(Field field:fields){
String modifier = Modifier.toString(field.getModifiers());
String type = field.getType().getSimpleName();
String name = field.getName();
System.out.println(modifier + " " + type + " " +name);
}
//通过反射调用private方法
try {
Person p = Person.class.newInstance();
//p.getPrivateMethod() error,not visiable
Method method = Person.class.getDeclaredMethod("getPrivateMethod",null);
method.setAccessible(true);
method.invoke(Person.class.newInstance());
} catch (Exception e) {
System.out.println(e);
}
//通过反射给成员变量赋值
try {
Field f = Person.class.getDeclaredField("name");
Person p = Person.class.newInstance();
f.setAccessible(true);
f.set(p, "xixi");
System.out.println(f.get(p));
} catch (Exception e) {
e.printStackTrace();
} System.out.println(Person.class.getClassLoader().getClass().getName());
}
} class Person implements Serializable{
private String name;
private int age;
public Person() { } public Person(String name, int age) {
this.age = age;
this.name = name;
}
public void setName(String name) throws IllegalArgumentException {
this.name = name;
} public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString(){
return "["+this.name+" "+this.age+"]";
} private void getPrivateMethod(){
System.out.println("this is a private method in Person Class");
}
}

  输出结果为:

[null  0]
[Rollen 20]
[null 0]
interface of which Person Class implements: [interface java.io.Serializable]
super class of Person Class: Object
public String toString()
public String getName()
public void setName(String) throws IllegalArgumentException
private void getPrivateMethod()
public int getAge()
private String name
private int age
this is a private method in Person Class
xixi
sun.misc.Launcher$AppClassLoader

  需要注意的是,类的Class在JVM中只有一份,我们通过反射将方法的修饰符由private改为了public,后面代码中这个方法的修饰符都将是public。

   我们还可以使用反射来实现工厂模式,代码如下:

  

package rtti;

public class UseReflectForFactoryPattern {

    public static Fruit getCertainFruit(String fruitName){
Fruit f = null;
try {
f = (Fruit) Class.forName(fruitName).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return f;
} public static void main(String[] args) {
//这里使用的是完整的类型rtti.Apple,实际使用中可能只会知道类名,比如Apple
//可以新建properties文件,存储Apple和rtti.Apple的对应关系
Fruit f = getCertainFruit("rtti.Apple");
f.eat();
f = getCertainFruit("rtti.Orange");
f.eat();
}
}
interface Fruit{public abstract void eat();} class Apple implements Fruit{
@Override
public void eat() {
System.out.println("eat Apple!");
}
} class Orange implements Fruit{
@Override
public void eat() {
System.out.println("eat Orange!");
}
}

 3.动态代理基础

  Java中的Proxy类和InvocationHandler提供了动态代理的功能,动态代理还是利用了反射,在原Class的基础上重新生成了一个新的Class,从而可以对目标方法做一些操作。

  Java的动态代理要求被代理的类必须继承了接口,如果被代理的类没有继承了接口,可以可虑用cglib来完成。

  下面是一个Proxy类和InvocationHandler完成动态代理的例子。

package rtti;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; public class JDKRroxy implements InvocationHandler{
private Object obj; public Object bind(Object obj){
this.obj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
.getClass().getInterfaces(), this);
} public static void main(String[] args) {
JDKRroxy jr = new JDKRroxy();
test t = (test) jr.bind(new ActiveTest()); //error: ActiveTest at = (ActiveTest) jr.bind(new ActiveTest());
t.testMethod();
} @Override
public Object invoke(Object paramObject, Method method, Object[] args) throws Throwable {
System.out.println("before method!");
Object temp = method.invoke(this.obj, args);
System.out.println("after method!");
return temp;
} } interface test{public abstract void testMethod();}
//use JDK Proxy must implements interface
class ActiveTest implements test{
public void testMethod(){
System.out.println("this is a test method!");
}
}
//use cglib,see :http://www.cnblogs.com/lnlvinso/p/4240350.html

  输出结果为:

before method!
this is a test method!
after method!

  

《Thinking in Java》学习笔记(六)的更多相关文章

  1. java学习笔记六——数组

    数组类型 数组是一种常见的数据结构,可用于存放多个数据,每一个数组元素存放一个数据,通常可以通过下标进行访问其元素. Java数组要求所有数组元素具有相同的数据类型.因此,数组元素的数据类型是唯一的. ...

  2. Java学习笔记六(I/O流)

    1.介绍 在实际开发过程中经常会用到数据的输入/输出操作,本篇博客着重分析一下,java中经经常使用到的有关IO操作的类.而在java中能够将经常使用的流分为两个部分:字节流和字符流. 1.流的抽象基 ...

  3. Java 学习笔记 (六) Java 定义变量

    这个问题来自于head first一书page68. package com.idea.study; public class Books { //headfirst page68 String ti ...

  4. Java学习笔记六:Java的流程控制语句之if语句

    Java的流程控制语句之if语句 一:Java条件语句之if: 我们经常需要先做判断,然后才决定是否要做某件事情.例如,如果考试成绩大于 90 分,则奖励一朵小红花 .对于这种“需要先判断条件,条件满 ...

  5. Java学习笔记六 常用API对象二

    1.基本数据类型对象包装类:见下图 public class Test { public static void main(String[] args){ Demo(); toStringDemo() ...

  6. 20145330第六周《Java学习笔记》

    20145330第六周<Java学习笔记> . 这周算是很忙碌的一周.因为第六周陆续很多实验都开始进行,开始要准备和预习的科目日渐增多,对Java分配的时间不知不觉就减少了,然而第十和十一 ...

  7. java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

    java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...

  8. Java IO学习笔记六:NIO到多路复用

    作者:Grey 原文地址:Java IO学习笔记六:NIO到多路复用 虽然NIO性能上比BIO要好,参考:Java IO学习笔记五:BIO到NIO 但是NIO也有问题,NIO服务端的示例代码中往往会包 ...

  9. 【Java学习笔记之二十六】深入理解Java匿名内部类

    在[Java学习笔记之二十五]初步认知Java内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意 ...

  10. 0035 Java学习笔记-注解

    什么是注解 注解可以看作类的第6大要素(成员变量.构造器.方法.代码块.内部类) 注解有点像修饰符,可以修饰一些程序要素:类.接口.变量.方法.局部变量等等 注解要和对应的配套工具(APT:Annot ...

随机推荐

  1. Codeforces 626C Block Towers(二分)

    C. Block Towers time limit per test:2 seconds memory limit per test:256 megabytes input:standard inp ...

  2. Gym100814B Gym100814F Gym100814I(异或) ACM International Collegiate Programming Contest, Egyptian Collegiate Programming Contest (2015) Arab Academy for Science and Technology

    今日份的训练题解,今天写出来的题没有昨天多,可能是因为有些事吧... Gym100814B 这个题就是老师改卷子,忘带标准答案了,但是他改了一部分卷子,并且确定自己改的卷子没出错,他想从改过的卷子里把 ...

  3. Spring框架学习笔记(7)——代理对象实现AOP

    AOP(面向切面编程) AOP(Aspect-Oriented Programming, 面向切面编程): 是一种新的方法论, 是对传统 OOP(Object-Oriented Programming ...

  4. io流读取文件

    package test; import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import ...

  5. [国嵌攻略][160][SPI驱动程序设计]

    SPI Flash驱动 1.打开/drivers/mtd/devices/m25p80.c驱动文件.找到初始化m25p80_init函数,其中通过spi_register_driver来注册spi设备 ...

  6. UE4 多线程(一)

    UE4中使用多线程的有两种方式,一种方式就是使用FRunnable和FRunnableThread,另一种方式是Task Graph System.Task Graph System有时会占用游戏线程 ...

  7. myeclipse中git的使用

    1.右键项目,team-->commit,勾选修改了的文件,点击commit(将更新提交到本地仓库)2.右键项目,team-->pull,合并本地仓库和远程服务器仓库,pull后有一些文件 ...

  8. dede后台登陆后一片空白的解决办法汇总

    dede后台登陆后一片空白的第一种解决办法: 找到:include/common.inc.php文件,打开,查找程序代码://error_reporting(E_ALL);error_reportin ...

  9. vue2.0集成百度UE编辑器,上传图片报错!!!

    我这边配置进去之后,界面加载,文本输入都没有问题,就是上传图片会有问题 这张图, 左边红色框框 就是目录结构咯, 右边红色框框 就是各种网上教程给出的第一个路径配置对吧, 下面的就是绿色 服务器接口配 ...

  10. javascript中window.location.search的用法和作用。

    用该属性获取页面 URL 地址: window.location 对象所包含的属性 属性 描述 hash 从井号 (#) 开始的 URL(锚) host 主机名和当前 URL 的端口号 hostnam ...