枚举 enum
public enum TrafficLamp{
RED(30){
public TrafficLamp nextLamp(){
return GREEN;
}
},
GREEN(45){
public TrafficLamp nextLamp{
return YELLOW;
}
},
YELLOW(5){
public TrafficLamp nextLamp{
return RED;
}
};
public abstract TrafficLamp nextLamp();
private int time;
private TrafficLamp(int time){this.time=time;}
}
--------------------------------------------------------------------------
Class类
java中的各个java类属于同一类事物,描述这类事物的Java类名就是Class.
Class cls1=Date.class;字节码1
Class cls2=Person.class;字节码2;
每个字节码就是Class的实例对象
如何得到各个字节码对应的实例对象(Class类型)
三种得到Class对象的方法
类名.class
对象.getClass()
Class.forName("类名")
String str1="kingkong";
Class cls1=str1.getClass();
Class cls2=String.class;
Class cls3=Class.forName(java.lang.String);
三种Class得到的字节码都是一样的
Class.isPrimitive(),是否是基本类型
Class.isArray(),是否是数组类型
-----------------------------------------------------------------------------------------------------
反射
反射就是把java类中各种成分映射成相应的java类。
Constructor类
Constructor constructors[]=Class.forName("java.lang.String").getConstructor();
Constructor constructor1=String.class.getConstructor(StringBuffer.class);
String str2=(String)constructor1.newInstance(new StringBuffer("abc"));
class->constructor-->new object
String obj=(String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法构建实例对象。
Field类代表成员变量
public class ReflectPoint{
private int x;
public int y;
ReflectPoint(int x,int y){
this.x=x;
this.y=y;
}
}
ReflectPoint pt1=new ReflectPoint(3,5);
Field filedY=pt1.getClass().getField("y");
fieldY.get(pt1);
Field fieldX=pt1.getClass().getField("x");
fieldX.setAccessible(true);
fieldX.get(pt1);
成员变量反射的综合案例
public class ReflectPoint{
private int x;
public int y;
public String str1="ball";
public String str2="baseketball";
public String str3="kingkong";
ReflectPoint(int x,int y){
super();
this.x=x;
this.y=y;
}
@Override
public String toString(){}
}
private static void changeStringValue(Object obj)throws Exception{
Field[] fields=obj.getClass().getFields();
for(Field field:fields){
if(field.getType()==String.class){
String oldValue=(String)field.get(obj);
String newValue=oldValue.replace('b','a');
field.set(obj,newValue);
}
}
}
Method方法
//str1.charAt(1);
Method methodCharAt=String.class.getMethod("charAt",int.class);
methodCharAt.invoke(str1,1);
如果invoke第一个参数是null,说明method是静态方法
对接受数组参数成员方法进行反射
String startingClassName=arg[0];
Method mainMethod=Class.forName(startClassName).getMethod("main",String[].class);
mainMethod.invoke(null,(object)new String[]{"111","222","333"});
数组的反射
int [] a1=new int[3];
int [] a2=new int[4];
int [][] a3=new int[2][3];
String [] a4=new String[4];
String [] a4=new String[]{"aa","bb","cc"};
System.out.println(a1.getClass()==a2.getClass());//true
System.out.println(a1.getClass()==a3.getClass());//false
a1.getClass().getSuperclass().getName();
Object[] aObj4=a3;
Object[] aObj5=a4;
数组反射的应用
private static void printObject(Object obj){
Class Objclass=obj.getClass();
if(Objclass.isArray()){
int len=Array.getLength(obj);
for(int i=0;i<len;i++){
System.out.println(Array.get(obj,i));
}
}
else
System.out.println(obj);
}
practice
Collection collections=new ArrayList();
RefflectPoint pt1=new RefflectPoint(3,3);
RefflectPoint pt2=new RefflectPoint(5,5);
RefflectPoint pt3=new RefflectPoint(3,3);
collections.add(pt1);
collections.add(pt2);
collections.add(pt3);
collections.add(pt1);
ArrayList 是有顺序的集合,HashSet先判断此集合中是否存在当前对象
HashCode方法与HashSet类
哈希值分成多个区域,然后先找到区域在判断
---------------------------------------------------------------------------------
JavaBean是一种特殊的Java类
方法的名字是以set和get开头
---------------------------------------------------------------------------------
反射技术开发框架的原理
配置文件中定义:className=java.util.ArrayLis;
InputStream ips=new FileInputStream(config.properties);
Properties props=new Properties();
props.laod(ips);
ips.close();
String className=(Collection)Class.forName(className);
InputStream ips=
class.getClassLoader().getResourseAsStream(config.properties);
配置文件存放在classpath目录下
---------------------------------------------------------------------
注解
public class AnnotationTest{
@SuppressWarnings("deprecation")
@Deprecated
@override
}
---------------------------------------------------------------------
泛型
ArrayList<Integer> collection=new ArrayList<Integer>();
collection.getClass().getMethod("add",Object.class).invoke(collection3,"abc");
泛型是为了安全,给编译器设定的
HashMap<String,Integer>map=new HashMap<String,Integer>();
map.put();
Set<Map.Entry<String,Integer>>entrySet=map.entrySet();
for(Map.Entry<String,Integer>entry :entrySet){
entry.getKey();
entry.getValue();
}
通过反射活的泛型的实际参数
Mthode applyMethod=GenericTest.class.getMethod("applyVector",Vector.class);
Type[] types=applyMethod.getGenericParameterTypes();
parameterizedType pType=(Parameterized)types[0];
pType.getRawType();
pType.getActualTypeArguments()[0];
------------------------------------------------------------------------------------
代理
代理类的每个方法调用目标类相同方法,并在调用方法时加上系统功能的代码。
JVM可以再运行期动态生成类的字节码,这种动态生成的类往往用作动态代理类
代理类的各个方法中同城除了要调用的目标的相应方法和对外返回目标返回结果外,
还可以再代理方法中的如下位置加上系统功能代码。
在调用目标方法之前,在调用目标方法之后,在调用目标方法前后,在处理目标方法异常的catch块中
Class clazzProxy1=Proxy.getProxyClass(collection.class.getClassLoader(),Collection.class);
clazzProxy1.getName();
Constructor[] constructors=clazzProxy1.getConstructors();
for(Constructor constructor:constructors){
String name=constructor.getName();
StringBuilder sBuilder=new StringBuilder(name);
sBuilder.append('(');
Class[] clazzParams=constructor.getParameterType();
for(Class clazzParam:clazzParams){
sBuilder.append(clazzParam.getName().append(','));
}
}
StringBuffer使用与多线程,StringBuilder使用与单线程
创建动态类的实例对象及调用方法
Constructor constructor=clazzProxy1.getConstructor(InvocationHandler.class);
//InvocationHandler是接口,需要实现
class MyInvocationHandler1 implements InvocationHandler{
//完成InvocationHandler对象的内部功能
//可以使用匿名内部类
}
Collection proxy1=(Collection)constructor.newInstance(new MyInvocationHandler());
Collection proxy2=(Collection)Proxy.newProxyInstance(
Collection.class.getClassLoader(),
new Class[](Collection.class),
new InvocationHandler(){
public Object invoke(Object proxy,Method method,Object[] args)
throws Throwable{
return null;
}
}
);
怎样将目标类传进去?
1.直接在InvocationHandler实现类中创建目标类的实例对象
2.为InvocationHandler实现类注入目标类的实例对象,不能采用匿名内部类形式
3.让匿名的InvocationHandler实现类访问外面方法中的目标类实例对象的final类型的引用变量
和动态代理有关的有两个类
1.interface InvocationHandler
Object invoke(Object proxy, Method method, Object[] args)
只这一个方法,后面再说
2.class Proxy
真正表示动态代理的类,提供两个静态方法:
Class<?> getProxyClass(ClassLoader loader, Class<?>[] interface)
用来产生代理类,参数要提供interface数组,它会生成这些interface的“虚拟实现”,
用来冒充真实的对象。
Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
产生代理对象,多了InvocationHandler参数(只是InvocationHandler接口的实现类),
它与代理对象关联,当请求分发到代理对象后,会自动执行h.invoke(...)方法,
接口
public interface Hello {
void sayHello(String to);
void print(String p);
}
实现类
public class HelloImpl implements Hello {
public void sayHello(String to) {
System.out.println("Say hello to " + to);
}
public void print(String s) {
System.out.println("print : " + s);
}
}
在这里生成与代理类相关联的InvocationHandler对象
public class LogHandler implements InvocationHandler {
private Object dele;
public LogHandler(Object obj) {
this.dele = obj;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
doBefore();
//在这里完全可以把下面这句注释掉,而做一些其它的事情
Object result = method.invoke(dele, args);
after();
return result;
}
private void doBefore() {
System.out.println("before....");
}
private void after() {
System.out.println("after....");
}
}
public class ProxyTest {
public static void main(String[] args) {
HelloImpl impl = new HelloImpl();
LogHandler handler = new LogHandler(impl);
//这里把handler与impl新生成的代理类相关联
Hello hello = (Hello) Proxy.newProxyInstance(impl.getClass().getClassLoader(), impl.getClass().getInterfaces(), handler);
//这里无论访问哪个方法,都是会把请求转发到handler.invoke
hello.print("All the test");
hello.sayHello("Denny");
}
}