黑马程序员__枚举__反射__内省
来源:互联网 发布:大数据服务器硬件配置 编辑:程序博客网 时间:2024/04/28 11:38
--------- android培训、java培训、期待与您交流! ------------
MyEclipse是Eclipse的插件
透视图是视图的组合
到Window-- >Show View -- >other里找相应视图
导入工程:先把工程COPY到工作间,导入Existing Projects intoWorkspace
再配JDK,Build Path - - >configure Build Path,把Libraries里原来的删除掉,添加新的add Lib
alt+/内容助理
import static java.lang.Math.*;//静态导入
可变参数的特点:
只能出现在参数列表的最后,位于变量类型和变量名之间,前后有无空格都可以
调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中
以数组的形式访问可变参数
享元模式:flyweight很多个小的对象,它们有很多属性相同,把它们变成一个对象,那些不同的属性把它们变成方法的参数,称之为外部状态,那些相同的属性称之为这些对象的内部状态
枚举:
把字符串变成枚举中对应的对象: WeekDay.valueOf("SUN");
WeekDay.values();得到枚举中所有元素的数组
枚举类定义的东西都要位于元素列表之后,这时元素列表后面要用个分号;
枚举类的构造方法都要私有
public enum TrafficLamp{RED(30){public TrafficLamp nextLamp(){return GREEN;}},GREEN(30){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类描述了哪些方面的信息呢?
类的名字,类的访问属性,类所属于的包名,字段名称的列表,方法名称的列表,等等
如何得到各个字节码对应的实例对象(Class类型)
类名.class,例如System.class
对象.getClass(),例如new Date().getClass()
Class.forName("类名"),例如Class.forName("java.util.Date");//反射常用
九个预定义Class实例对象
void.class和八个基本数据类型int.class
int.class == Integer.class;结果为false
int.class == Integer.TYPE;结果为true,TYPE为对象包装的基本类型的字节码
数组类型的Class实例对象
Class.isArray()
反射就是把Java类中的各种成分映射成相应的java类
表示Java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法
,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,
它们是Field,Method,Contructor,Package等等
Constructor类
Constructor类代表某个类中的一个构造方法
得到某个类所有的构造方法
Constructor[] constructors = Class.forName("java.lang.String").getConstructors();
得到某一个构造方法
Constructor constructor =
Class.forName("java.lang.String").getConstructor(StringBuffer.class);
//获得方法时要用到类型
因为JDK1.5的可变参数新特性,使getConstructor里可以传多个参数
用constructor.newInstance(new StringBuffer("abc"))创建对象时要对其进行强转(String)
创建实例对象
通常方式String str=new String(new StringBuffer("abc"));
反射方式String str=(String)constructor.newInstance(new StringBuffer("abc"));
//调用获得的方法时要用到上面相同类型的实例对象
Class.newInstance()方法
例子:String obj=(String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象
该方法内部的具体代码是怎样写的呢?用到了缓存机制来保存默认构造方法的实例对象
ReflectPoint pt1=new ReflectPoint(3,5);
Field fieldY=pt1.getClass().getField("y");//只能取得public上的
//fieldY的值是多少?是5,错!fieldY不是对象身上的变量,而是类上,
//要用它去取某个对象上对应的值
fieldY.get(pt1);//取得pt1对象上y的值
Field fieldX=pt1.getClass().getDeclaredField("x");//只要是声明过的就可以取得
fieldX.setAccessible(true);//暴力反射,设置为可访问
fieldX.get(pt1);
Method类
Method类代表某个类中的一个成员方法
得到类中的某一个方法
例子Method charAt =
Class.forName("java.lang.String").getMethod("charAt",int.class);
调用方法:
通常方式:System.out.println(str.charAt(1));
反射方式:System.out.println(charAt.invoke(str,1));
如果传递给Method对象的invoke()方法的第一个参数为null,
说明该Method对象对应的是一个静态方法!
用反射方式执行某个类中的main方法
目标:写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法
问题:
启动Java程序的mian方法的参数是一个字符串数组,即String[] args,通过反射
方式来调用这个main方法时,如何为invoke方法传递参数呢?按JDK1.5的语法,整个
数组是一个参数,而按JDK1.4的语法,数组中的每个元素对应一个参数,当把一个字
符串数组作为参数传递给invoke方法时,javac会到底按照哪种清洁进行处理呢?
JDK1.5肯定要兼容JDK1.4的语法,会按JDK1.4的语法进行处理,即把数组打散成为
若干个单独的参数,所以在给main方法传递参数时,不能使用代码
mainMethod.invoke(null,new String[]{"xx"}),javac只把它当作JDK1.4的语法进行理解
而不把它当作JDK1.5的语法解释,因此会出现参数类型不对的问题
解决办法:
mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});
mainMethod.invoke(null,(Object)new String[]{"xxx"});编译器会作特殊处理,编译
时不把参数当作数组看待,也就不会数组打散成若干个参数了
每一个具有相同元素类型和相同维度的数组反射的Class都是同一个
框架要解决的核心问题:若干年前的框架调用若干年后写的程序
一定要记住用完整的路径存放properties文件,但完整的路径不是硬编码,而是运算出来的
示例代码
package cn.itcast.day1;import java.io.FileInputStream;import java.io.InputStream;import java.util.ArrayList;import java.util.Collection;import java.util.HashSet;import java.util.Properties;public class ReflectTest2 {public static void main(String[] args) throws Exception{//InputStream ips = new FileInputStream("config.properties");//读取properties配置文件//InputStream ips = ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/day1/config.properties");//类加载器加载根目录下相应位置的配置文件InputStream ips = ReflectTest2.class.getResourceAsStream("config.properties");Properties props = new Properties();props.load(ips);ips.close();String className = props.getProperty("className");Collection collections = (Collection)Class.forName(className).newInstance();//Collection collections = new HashSet();ReflectPoint pt1 = new ReflectPoint(3,3);ReflectPoint pt2 = new ReflectPoint(5,5);ReflectPoint pt3 = new ReflectPoint(3,3);collections.add(pt1);collections.add(pt2);collections.add(pt3);collections.add(pt1);System.out.println(collections);}}
内省(Introspector)
JavaBean是一种特殊的Java类,主要用于传递数据信息,这种Java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(ValueObject,简称VO)这些信息在类中用私有字段来存储,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问,大家觉得这些方法的名称叫什么好呢?JavaBean的属性是根据其中的setter和getter方法来确定的,而不是根据其中的成员变量,如果方法名为setId,中文意思即为设置id,至于你把它夏至哪个变量上,用管吗?如果方法名为getId,中文意思即为获取id至于你从哪个变量上取,用管吗?去掉set前缀,剩余部分就是属性名,如果剩余部分的第二个字母是小写的,则把剩余部分的首字母改成小的
setId()的属性名id,isLast()的属性名last,setCPU的属性名是CPU
总之,一个类被当作JavaBean使用时,JavaBean的属性是根据方法名推断出来的,它根本看不到Java类内部的成员变量
一个符合JavaBean特点的类可以当作普通类一样进行使用,但把它当JavaBean用肯定需要带来一些额外的好处,我们才会去了解和应用JavaBean,好处如下
1. 在Java EE开发中,经常要使用到JavaBean,很多环境就要求按JavaBean方式进行操作,别人都这么么用和要求这么做,那你就没什么挑选的余地
2. JDK中提供了对JavaBean进行操作的一些API,这套API就称为内省,如果要你自己去通过getX方法来访问私有的x怎么做,有一定难度,用内省这套API操作JavaBean比用普通类的方式更方便
采用遍历BeanInfo的所有属性方式来查找和设置某个ReflectPoint对象的x属性,在程序中把一个类当作JavaBean来看,就是调用IntroSpector.getBeanInfo方法,得到的BeanInfo对象封装了把这个类当作JavaBean看的结果信息
内省示例
package cn.itcast.day1;import java.beans.BeanInfo;import java.beans.IntrospectionException;import java.beans.Introspector;import java.beans.PropertyDescriptor;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import org.apache.commons.beanutils.BeanUtils;import org.apache.commons.beanutils.PropertyUtils;import cn.itcast.day1.ReflectPoint;public class IntroSpectorTest {/** * @param args */public static void main(String[] args) throws Exception{// TODO Auto-generated method stubReflectPoint pt1 = new ReflectPoint(3,5);String propertyName = "x";Object retVal = getProperty(pt1, propertyName);System.out.println(retVal);Object value = 7;setProperty(pt1, propertyName, value);System.out.println(BeanUtils.getProperty(pt1, "x"));BeanUtils.setProperty(pt1, "x", 8);System.out.println(pt1.getX());BeanUtils.setProperty(pt1, "birthday.time", "111");System.out.println(BeanUtils.getProperty(pt1, "birthday.time"));PropertyUtils.setProperty(pt1, "x", 7);System.out.println(PropertyUtils.getProperty(pt1, propertyName).getClass());}private static void setProperty(Object pt1, String propertyName,Object value) throws IntrospectionException,IllegalAccessException, InvocationTargetException {PropertyDescriptor pd2 = new PropertyDescriptor(propertyName,pt1.getClass());Method methodSetX = pd2.getWriteMethod();//通过getWriteMethod方法获取属性名pd的set方法methodSetX.invoke(pt1, value);}private static Object getProperty(Object pt1, String propertyName)throws IntrospectionException, IllegalAccessException,InvocationTargetException {/*PropertyDescriptor pd = new PropertyDescriptor(propertyName, pt1.getClass());Method methodGetX = pd.getReadMethod();//通过getReadMethod方法获取属性名pd的get方法Object retVal = methodGetX.invoke(pt1);*/ BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass());PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();Object retVal = null;//遍历pds查找propertyName属性名并保存到retVal中for(PropertyDescriptor pd : pds){if(pd.getName().equals(propertyName)){Method methodGetX = pd.getReadMethod();retVal = methodGetX.invoke(pt1);break;}} return retVal;}}
用到的ReflectPoint
package cn.itcast.day1;import java.util.Date;public class ReflectPoint {private Date birthday = new Date();private int x;public int y;public int getX() {return x;}public void setX(int x) {this.x = x;}public int getY() {return y;}public void setY(int y) {this.y = y;}public String str1 = "ball";public String str2 = "basketball";public String str3 = "itcast";public ReflectPoint(int x, int y) {super();this.x = x;this.y = y;}@Overridepublic String toString(){return x+":"+y;}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + x;result = prime * result + y;return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;ReflectPoint other = (ReflectPoint) obj;if (x != other.x)return false;if (y != other.y)return false;return true;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}}
导入外部的Jar包,在工程上建一个lib目录用于存放jar包
在jar包上右键-- >build path -- >add to build path
用apache的BeanUtils.jar包的时候还要导入logging包
--------- android培训、java培训、期待与您交流! ------------
- 黑马程序员__枚举__反射__内省
- 黑马程序员__枚举
- 黑马程序员__反射
- 黑马程序员__反射
- 黑马程序员__反射
- 黑马程序员__反射基础
- 黑马程序员__内省和JavaBean
- 黑马程序员Java高新__枚举
- 黑马程序员Java高新__反射
- 黑马程序员__泛型以及反射
- 黑马程序员__java基础__反射
- 黑马程序员__俄罗斯方块
- 黑马程序员__多线程
- 黑马程序员__基础知识
- 黑马程序员__泛型
- 黑马程序员__多线程
- 黑马程序员__异常
- 黑马程序员__多线程
- USB 协议原理
- word中中间某页开始插入页码和某页开始重新编号方法
- 判断两个单链表是否相交
- Maven Help插件的使用
- crontab执行失败:CRON (oracle) ERROR: cannot set security context
- 黑马程序员__枚举__反射__内省
- cocos2d-x中为道具添加数量并对数量进行增减操作的实现
- #import、#include 的区别
- 锁概念 以及 例程说明
- Eclipse开发环境搭建 .
- 简单的注册程序的后台代码
- Android学习笔记
- C#中加载dll的问题
- 推荐英语学习几本好书