Java高级教程
反射:
反射的基石:Class类
Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class。
如何获取Class的实例对象?
1,Classcs1=类名.class;
2,Classcs2=对象.getClass();
3,Classcs3=Class.forName(“类的完整名称”)
九个预定义的Class对象(八个基本类型,及void)
反射就是把Java类中的各种成分映射成相应的java类。
Constructor类:代表某个类中的一个构造方法
得到某个类所有的构造方法:
Constructor[]constructors=Class.forName(“java.lang.String”).getConstructors();
得到某一个构造方法:
Constructorconstructor= Class.forName(“java.lang.String”).getConstructors(StringBuffer.class);
创建实例对象:
通常方式:Stringstr=new String(new StringBuffer(“abc”));
反射方式:Stringstr=(String)constructor.newInstance(new StringBuffer(“abc”));
Class.newInstance()方法:
例子:Stringobj=(String)Class.forName(“java.lang.String”).newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。
Class有自己的newInstance方法(无参数,省去获取constructor这一步)。
通常创建某个类的实例 class--constructor—object
现在 Class—object(class.newInstance())
Field(成员变量)类使用,代码:
publicclass staticimport
{
publicstaticvoid main(String[] args)throws Exception
{
reflectPoint pt1=new reflectPoint(3,5);
Field fieldy=pt1.getClass().getField("y");
fieldy.get(pt1);//取出变量在pt1对象上的值
System.out.println(fieldy.get(pt1));
pt1=new reflectPoint(3,26);
System.out.println(fieldy.get(pt1));
Fieldfieldx=pt1.getClass().getDeclaredField("x");//访问某个类的私有变量
fieldx.setAccessible(true);//设置访问权限
System.out.println(fieldx.get(pt1));
}
}
class reflectPoint
{
privateintx;
publicinty;
public reflectPoint(int x,int y)
{
super();
this.x = x;
this.y = y;
}
}
Method(方法)类:
得到类中的某一个方法:
例子: Method charAt=Class.forName(“java.lang.String”).grtMethod(“charAt”,int.class);()内为参数名,参数类型。
调用方法:
通常方式:System.out.println(str.charAt(1));
反射方式:System.out.println(charAt.invoke(str,1));
如果传递给invoke()方法的第一个参数是null,说明该method对象对应的是一个静态方法!
Method类运用代码:(用反射方式执行某个类中的main方法)
解决方法:
publicclass ReflectDemo
{
publicstaticvoid main(String[] args)throws Exception
{
String startClass=args[0];
Method me=Class.forName(startClass).getMethod("main",String[].class);
me.invoke(null,(Object)new String[]{"111","222","333"});
//(Object)new String[]{"111","222","333"},(object)告诉编译器这是一个对象,让编译器不要自动拆包,或者这样写代码:new Object[]{new String[]{"111","222","333"}}
}
}
class printDemo
{
publicstaticvoid main (String[] args)
{
for(String ar:args)
{
System.out.println(ar);
}
}
}
数组的反射类型:具有相同参数类型和相同维度的数组具有相同的字节码。
如:int[] a1=newint[3];
int [] a2=newint[4];
int [][] a3=newint[2][3];
String[] a4=newString[4];
System.out.println(a1.getClass()== a2.getClass());
System.out.println(a1.getClass().equals(a3.getClass()));
System.out.println(a1.getClass().equals(a4.getClass()));
运行结果为:true,false,false
数组的反射应用
代码:
package Reflect;
import java.lang.reflect.Array;
publicclassArrayReflect
{
publicstaticvoid main(String[] args)
{
int[] a1=newint[]{1,2,3};
printObj(a1);
printObj("dfkljadjk");
}
publicstaticvoid printObj(Object obj)
{
Classclazz=obj.getClass();
if(clazz.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);
}
}
运行结果:1
2
3
dfkljadjk
JavaBean是一种特殊的Java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。
JDK中提供了对JavaBean进行操作的一些API,这套API就称为内省。
具有set()和get()方法的类可以视为JavaBean类。
JavaBean使用:
代码:
importjava.beans.IntrospectionException;
importjava.beans.PropertyDescriptor;
import java.lang.reflect.*;
import java.util.Map;
importorg.apache.commons.beanutils.BeanUtils;
importorg.apache.commons.beanutils.PropertyUtils;
publicclass JavaBeanDemo
{
publicstaticvoid main(String[] args)throws Exception
{
Inta ia=new Inta(2,8);
String propertyName="x";
Object retVal =getProperty(ia, propertyName);
System.out.println(retVal);
Object value=9;
setProperties(ia,propertyName, value);
System.out.println(BeanUtils.getProperty(ia,"x"));
BeanUtils.setProperty(ia,"x", 12);
System.out.println(ia.getX());
BeanUtils.setProperty(ia,"birthday.time", "111"); System.out.println(BeanUtils.getProperty(ia,"birthday.time"));
//BeanUtils是以字符串的形式对JavaBean进行操作,而PropertyUtils是以属性本//身的类型对JavaBean进行操作。
PropertyUtils.setProperty(ia,"x", 11);
System.out.println(PropertyUtils.getProperty(ia,"x"));
}
privatestaticvoid setProperties(Inta ia, String propertyName, Object value)
throws IntrospectionException,IllegalAccessException,
InvocationTargetException {
PropertyDescriptor pds2=new PropertyDescriptor(propertyName,ia.getClass());
Method methodSetX=pds2.getWriteMethod();
methodSetX.invoke(ia,value);
}
privatestatic Object getProperty(Inta ia, String propertyName)
throws IntrospectionException, IllegalAccessException,
InvocationTargetException {
PropertyDescriptor pds=new PropertyDescriptor(propertyName,ia.getClass());
Method methodGetX=pds.getReadMethod();
Object retVal=methodGetX.invoke(ia);
return retVal;
}
}
import java.util.Date;
publicclassInta{
privateintx,y;
private Datebirthday =new Date();
publicint getX() {
returnx;
}
publicvoid setX(int x) {
this.x = x;
}
publicint getY() {
returny;
}
publicvoid setY(int y) {
this.y = y;
}
public Date getBirthday() {
returnbirthday;
}
publicvoid setBirthday(Date birthday) {
this.birthday = birthday;
}
public Inta(int x,int y) {
super();
this.x = x;
this.y = y;
}
}
Java注解
注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类字段,方法,方法的参数以及局部变量上。
Java.lang.annotation
为注解增加基本属性
什么是注解的属性
一个注解相当于一个胸牌,如果你胸前贴了一个胸牌,就是传智播客的学生,否则,就不是。如果还想区分出是传智播客哪个班的学生,这时候可以为胸牌再增加一个属性来进行区分。加了属性的标记效果为:@MyAnnotaiton(color=”red”)
定义基本类型的属性和应用属性:
在注解类中增加String color();
@MyAnnotation(color=”red”)
用反射方式获得注解对应的实例对象后,再通过该对象调用属性对应的方法
MyAnnotation a =(MyAnotation)AnnotationTest.class.GetAnnotation(MyAnnotation.class);
System.outprintln(a.color());
可以认为上面这个@MyAnnotation是MyAnnotation类的一个实例对象
为属性指定缺省值
Stringcolor() default “yellow”;
Value属性:
Stringvalue() default “XXX”;
如果注解中有一个名称为value的属性,且你只想设置value属性(及其他属性都采用默认值或者你只有一个value属性),那么可以省略value=部分,例如@MyAnnotation(“YYY”);
为注解增加高级属性
数组类型的属性
Int []arrayAttr() default{1,2,3};
@MyAnnotation(arrayAttr={2,3,4})
如果数组属性中只有一个元素,这时候属性值部分可以省略大括号
枚举类型的属性
EnumTest.TrafficLamplamp();
@MyAnnotation(lamp=EnumTest.TrafficLamp.GREEN)
注解类型的属性
MetaAnnotationannotationAttr() default @MetaAnnotation(”XXX”);
@MyAnnotation(annotationAttr=@MetaAnnotation(“yyy”))
可以认为上面这个@MyAnnotation是MyAnnotation类的一个实例对象,同样的道理
,可以认为上面这个@MyAnnotation是MetaAnnotation类的一个实例对象,调用代码如下:
MetaAnnotation ma =myAnnotation.annotationAttr();
Java类加载器
Java类加载器将类的字节码加载到内存中,Java中有三个常用的类加载器,BootStrap,ExtClassLoader,AppClassLoader。因为类加载器也是Java类,它也需要被加载,因此需要有一个加载器不是Java类,BootStrap就是这个类。BootStrap是定义在JVM中的代码,而非Java字节码。
类加载器的管辖范围:
BootStrap:JRE/lib/rt.jar
ExtClassLoader:JRE/lib/ext/*.jar
AppClassLoader:CLASSPATH指定的所有Jar或目录
Java虚拟机加载类时,到底派那个类加载器去加载类呢?
首先当前线程的类加载器去加载线程中的第一个类;
如果类A中引用了类B,Java虚拟机将使用加载了类B的加载器加载类A。
还可以调用ClassLoader.getClass()方法来指定某个类加载器去加载调用方法这个类
编写自己的类加载器
自定义的类加载器必须继承ClassLoader
loadClass方法与findClass方法
defineClass方法
类加载器使用代码:对某个class文件加密(程序运行出错),再解密
-----classLoaderTest.java-----
import java.util.Date;
publicclass classLoaderTest {
publicstaticvoid main(String[] args)throws Exception {
ClassLoader cld=classLoaderTest.class.getClassLoader();
while(cld!=null)
{
System.out.println(cld.getClass().getName());
cld=cld.getParent();
}
System.out.println(cld);
// System.out.println(newClassLoaderAttachment().toString());
Class clazz=new MyClassLoader("itcast").loadClass("ClassLoaderAttachment");
Date d1=(Date)clazz.newInstance();
System.out.println(d1);
}
}
-----MyClassLoader.java-----
import java.io.*;
publicclass MyClassLoaderextends ClassLoader {
publicstaticvoid main(String[] args)throws IOException
{
String srcPath=args[0];
String destDir=args[1];
FileInputStream ips=new FileInputStream(srcPath);
String destFileName=srcPath.substring(srcPath.lastIndexOf("\\")+1);
String destPath=destDir+"\\"+destFileName;
FileOutputStream ops=new FileOutputStream(destPath);
cyper(ips,ops);
ips.close();
ops.close();
}
privatestaticvoid cyper(InputStream ips,OutputStream ops)throws IOException//加密算法,将二进制代码与0xff异或处理,即1变成0,0变成1。加密解 //密都用这个算法
{
int b=-1;
while((b=ips.read())!=-1)
{
ops.write(b ^ 0xff);
}
}
private StringclassDir;
@Override
protected Class<?>findClass(String name)throws ClassNotFoundException {
String ClassFileName=classDir+"\\"+name+".class";
try {
FileInputStream ips =new FileInputStream(ClassFileName);
ByteArrayOutputStream bos =new ByteArrayOutputStream();
cyper(ips,bos);
ips.close();
byte[] bytes = bos.toByteArray();
return defineClass(bytes, 0,bytes.length);
} catch (Exception e) {
e.printStackTrace();
}
returnsuper.findClass(name);
}
public MyClassLoader(){}
public MyClassLoader(StringclassDir)
{
this.classDir=classDir;
}
}
-----classLoaderAttachment.java-----
import java.util.Date;
publicclass ClassLoaderAttachmentextends Date
{
public String toString()
{
return"HelloHi!";
}
publicstaticvoid main(String[] args)
{
System.out.println("shenmea");
}
}
------- android培训、 java培训、期待与您交流! ----------