黑马程序员_基础加强二
来源:互联网 发布:信阳毛尖 知乎 编辑:程序博客网 时间:2024/05/16 08:27
------- android培训、java培训、期待与您交流! ----------
反射
1.反射就是把java类中的各种成分映射成相应的Java类。
2.反射的基石(class)java程序中的各个java类属于同一类事物,描述这类事物的java类名就是class。
3.反射的好处:大大增强了程序的扩展性。弊端:必须先明确类,在创建类的对象。
4.得到字节码对应的实例对象。
(1)类名.class
(2)对象.getClass()
(3)Class.forName("类名")
5.Class.forName("java.lang.String")
Class.forName的作用:返回字节码。
返回方式有两种:(1)这个字节码曾经被加载过,已存在于Java虚拟机中直接返回。
(2)Java虚拟机中还没有字节码,则用内加载器去加载把加载进来的字节码放在虚拟机中,以后要得到这份字节码就不用加载了。
6.只要是在源程序中出现的类型,都有各自的Class实例对象。
原始类型:System.out.println(int.class.isPrimitive());
数组类型System.out.println(int[].class.isArray());
Constructor类
1.代表某个类中的构造方法。
(1)得到某个了的所有构造方法
Constructor[]constructors = class.forName("java.lang.String").getConstructors();
(2)得到某一个构造方法
Constructor constructor1 =String.class.getConstructor(StringBuffer.class);
(3)创建实例对象
通常方式:String str = new String (new StringBuffer("abc"));
反射方式:String str2 = (String)constructor1.newInstance(newStringBuffer("abc"));
2.Class.newInstance()方法:该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。
Field类
1.代表某个类中的一个成员变量
2. getField();对所有公有变量获得字段
getDeclaredField();对所有私有变量获得字段
示例:
ReflectPoint pt1= new ReflectPoint(3,5);
FieldfieldY = pt1.getClass().getField("y");
//fieldY的值是多少?是5,错!fieldY不是对象上的变量,而是类上,要用它去取某个对象对应的值。
System.out.println(fieldY.get(pt1));
FieldfieldX = pt1.getClass().getDeclaredField("x");
fieldX.setAccessible(true);//将此对象的accessible标志设置为指示的布尔值。暴力反射
System.out.println(fieldX.get(pt1));
Method类
1.代表某个类中的成员方法。
2.调用方法:
通常方式:System.out.println(str.charAt(1));
反射方式:System.out.println(charAt.invoke(str,1));
示例:
MethodmethodCharAt = String.class.getMethod("charAt", int.class);//得到类中的方法
System.out.println(methodCharAt.invoke(str1,1));
System.out.println(methodCharAt.invoke(str1,new Object[]{2}));
3.JDK1.4和JDK1.5的invoke方法的区别:
JDK1.5:publicobject invoke(Object obj,Object…args)
JDK1.6:publicobject invoke(Object obj,Object[] args)
即按JDK1.4的语法,需要将一个数组作为参数传递给invoke方法时,数组中的每个元素分别对应被调用方法中的一个参数,所以,调用charAt方法的代码也可以用JDK1.4改写为charAt.invoke("str", newObject[]{1}))形式。
用反射方式执行某个类中的main方法
1.main方法的参数是一个字符串,如果用反射的方法来调用main方法时,如何为invoke方法传递参数。
2.解决办法:
Method mainMethod = Class.forName(startingClassName).getMethod("main",String[].class);
//mainMethod.invoke(null, new Object[]{newString[]{"111","222","333"}});//第一种方法
mainMethod.invoke(null, (Object)newString[]{"111","222","333"});//第二种方法
编译器会做特殊的处理,编译时不把参数当作数组看待,也就不会把数组打散成若干个参数了。
数组的反射
1.具有相同维数和元素类型的数组属于同一个类型,即具有相同的calss的实例对象。
2.基本类型的一维数组可以被当作Object类型使用,不能当作object[]类型使用。
3.非基本类型的一维数组,既可以当作object类型使用,又可以当作object[]类型使用。
示例:
int [] a1 = newint[]{1,2,3};
String[] a4 = new String[]{"a","b","c"};
PrintObject(a1);
PrintObject(a4);
PrintObject("xyz");
private staticvoid PrintObject(Object obj) {
Class clazz = 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.因为在写程序时无法知道要被调用的类名,所以在程序中无法直接new某个类的实例对象了,而要用反射方式来做。
示例:
public static void main(String[]args)throws Exception {
InputStreamips = ReflectTest2.class.getResourceAsStream("resource/config.properties");
//用类加载器配置文件
Propertiesprops = new Properties();
props.load(ips);
ips.close();
StringclassName = props.getProperty("className");
Collectioncollections = (Collection)Class.forName(className).newInstance();
ReflectPointpt1 = new ReflectPoint(3,3);
ReflectPointpt2 = new ReflectPoint(5,5);
ReflectPointpt3 = new ReflectPoint(3,3);
collections.add(pt1);
collections.add(pt2);
collections.add(pt3);
collections.add(pt1);
System.out.println(collections.size());
}//打印2
内省JavaBean
1.JavaBean是一种特殊的java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。
2.JavaBean的属性是根据其中的setter和getter方法来确定的,而不是根据其中的成员变量。总之:一个类被当作JavaBean使用时,JavaBean的属性是根据方法名推断出来的,他根本看不到java类内部的成员变量。
private static void setProperties(Pointpt1, String Name,Object value) throws Exception {
PropertyDescriptorpd2 = newPropertyDescriptor(PropertyName, pt1.getClass());
MethodmethodSetX = pd2.getWriteMethod();
methodSetX.invoke(pt1,value);
System.out.println(pt1.getX());
}
private static ObjectgetProperty(ReflectPoint pt1, String PropertyName)throws Exception {
PropertyDescriptorpd = newPropertyDescriptor(PropertyName, pt1.getClass());
Method methodGetX= pd.getReadMethod();
ObjectretVal = methodGetX.invoke(pt1);
return retVal;
}
BenUtils工具包
1.用BeanUtils类先get原来设置好的属性,再将其set为一个新值。get属性时返回的结果为字符串,set属性时可以接受任意类型的对象,通常使用字符串。
2.用PropertyUtil类先get原来设置好的属性,再将其set为一个新值。get属性时返回的结果为该属性本来的类型,set属性时只接受该属性本来的类型。
3.将jar包拷贝到工作间的一个文件下,右击Build Path,选择Add to Build Path。
类加载器
1.加载类的工具。
2.作用:在Java程序中用到一个类,出现了这个类的名字,那么Java虚拟机首先把类的字节码加载到内存里面来,通常字节码文件的原始信息放在硬盘上classpath指定目录下,把.class文件的内容加载到硬盘里面来,在对其进行处理,处理完的结果就是字节码,就把class文件从硬盘上加载进来,对其进行处理。
3.系统默认三个主要类加载器:BootStrap(JRE/lib/rt.jar),ExtClassLoader(JRE/lib/ext/*.jar),AppClassloader(Classpath指定所有jar或目录)。
4.类加载器的委托机制:每个类加载器加载类时,优先委托给其上级类加载器,当所有根类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛出classNotFoundException。
5.自定义的类加载器必须继承classLoader,loadclass方法与findClass方法,defineClass方法。
示例
编写对class文件进行加密的工具类
public class MyClassLoader extendsClassLoader {
publicstatic void main(String[] args)throws Exception {//加密部分
StringsrcPath = args[0];
StringdestDir = args[1];
FileInputStreamfis = new FileInputStream(srcPath);
StringdestFileName = srcPath.substring(srcPath.lastIndexOf('\\')+1);
StringdestPath = destDir +"\\"+destFileName;
FileOutputStreamfos = new FileOutputStream(destPath);
cypher(fis,fos);
fis.close();
fos.close();
}
privatestatic void cypher(InputStream ips,OutputStream ops)throws Exception{
intb = -1;
while((b= ips.read()) !=-1){
ops.write(b^0xff);
}
}
privateString classDir;
@Override//解密部分
protected Class<?> findClass(String name) throwsClassNotFoundException {
String calssFileName =classDir+"\\"+name.substring(name.lastIndexOf('.')+1)+".class";
try{
FileInputStreamfis = new FileInputStream(calssFileName);
ByteArrayOutputStreambos = new ByteArrayOutputStream();
cypher(fis,bos);
fis.close();
byte[]bytes = bos.toByteArray();
returndefineClass(bytes,0,bytes.length);
}catch(Exceptione){
e.printStackTrace();
}
return super.findClass(name);
}
publicMyClassLoader(String classDir){
this.classDir= classDir;
}
}
//调用类加载器
public class ClassLoaderTest {
publicstatic void main(String[] args) throws Exception {
System.out.println(
ClassLoaderTest.class.getClassLoader().getClass().getName()
);
System.out.println(System.class.getClassLoader());
ClassLoaderloader = ClassLoaderTest.class.getClassLoader();
while(loader !=null){
System.out.println(loader.getClass().getName());
loader= loader.getParent();
}
System.out.println(loader);
Classclazz =
newMyClassLoader("itcastlib").loadClass("cn.itcast.day2.ClassLoaderAttachment");
Dated1 = (Date)clazz.newInstance();
System.out.println(d1);
}
}
//进行加密处理,加密处理后存入itcastlib文件夹下
public class ClassLoaderAttachment extendsDate {
publicString toString(){
return"hello,itcast";
}
}
代理
1.代理就是为已存在的多个接口的目标类中的方法添加一些系统功能。
2.交叉业务:把安全,事务,日志等功能贯穿到好多个模块中。
3.重要原则:不要把供货商暴露给客户。
4.让jvm创建动态类及其实例对象,需要给他提供哪些信息?
三个方面:
(1)生成的类中有哪些方法,通过让其实现哪些接口的方式进行告知;
(2)产生的类字节码必须有一个关联的类加载器对象;
(3)生成的类中的方法的代码是怎样的,也得由我们提供,把我们的代码卸载一个约定好了的接口。对象的方法中,把对象传给他,他调用我的方法,即相当于插入了我的代码。提供执行代码的对象就是那个InvocationHander对象,他是在创建动态类的实例对象的构造方法时传递进去的了。在上面的InvocationHander对象的invoke方法中加一点代码,就可以看到这些代码别调用运行了。
5.用Proxy.newInstance方法直接一步就创建出代理对象。
Object obj =clazzProxy1.newInstance();
示例:创建动态的实例对象,用反射获得构造方法,编写一个最简单的InvocationHander类。
Class clazzProxy1 =Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
System.out.println(clazzProxy1.getName());
Constructor[]constructors = clazzProxy1.getConstructors();
for(Constructorconstructor : constructors){
Stringname = constructor.getName();
StringBuildersBuilder = new StringBuilder(name);
sBuilder.append('(');
Class[]clazzParams = constructor.getParameterTypes();
for(ClassclazzParam:clazzParams){
sBuilder.append(clazzParam.getName()).append(',');
}
if(clazzParams!=null&& clazzParams.length != 0)
sBuilder.deleteCharAt(sBuilder.length()-1);
sBuilder.append(')');
System.out.println(sBuilder.toString());
}
动态生成的类的内部代码
Method[]methods = clazzProxy1.getMethods();
for(Methodmethod : methods){
String name = method.getName();
StringBuildersBuilder = new StringBuilder(name);
sBuilder.append('(');
Class[]clazzParams = method.getParameterTypes();
for(ClassclazzParam:clazzParams){
sBuilder.append(clazzParam.getName()).append(',');
}
if(clazzParams!=null&& clazzParams.length != 0)
sBuilder.deleteCharAt(sBuilder.length()-1);
sBuilder.append(')');
System.out.println(sBuilder.toString());
}
------- android培训、java培训、期待与您交流! ----------
- 黑马程序员_基础加强(二)
- 黑马程序员_基础加强二
- 黑马程序员_基础加强
- 黑马程序员_基础加强
- 黑马程序员--基础加强(二)
- 黑马程序员_基础加强_枚举
- 黑马程序员_基础加强_反射
- 黑马程序员_基础加强_注解
- 黑马程序员_基础加强_代理
- 黑马程序员_基础加强_枚举
- 黑马程序员_基础加强_注解
- 黑马程序员_基础加强_反射
- 黑马程序员_基础加强_注解
- 黑马程序员_java基础加强_代理
- 黑马程序员_基础加强path1
- 黑马程序员_基础加强path2
- 黑马程序员_基础加强path3
- 黑马程序员_基础加强小结
- HDU 1094(水题)
- 郴州市那家医院治疗早泄比较好?
- 谈谈Linux下动态库查找路径的问题
- HDU 1095(水题)
- 企业发布无线安装APP
- 黑马程序员_基础加强二
- HDU 1096(水题)
- yii 应用
- ubuntu jdk环境变量配置
- 俞永福:未来的1800天,创业者去哪儿?
- html校验3
- 我们为什么要使用NodeJS
- PKI编程
- 黑马程序员_基础加强三