黑马程序员_JAVA_枚举和反射总结
来源:互联网 发布:画房间平面图软件 编辑:程序博客网 时间:2024/05/21 16:56
枚举的介绍
枚举:
1. 为什么要有枚举
问题:要定义星期几或者性别的变量,该怎么定义呢?假设1-7分别表示星期一到星期日,单有人可能会写成int weekday=0;
枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错,枚举可以让编译器编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现这一目标
枚举的基本应用
用普通类模拟枚举的实现原理
package com.itcast.day1; public abstract class WeekDay{ private WeekDay() { } public finalstatic WeekDay SUN=newWeekDay() { @Override public WeekDay nextDay() { return MON; } }; public finalstatic WeekDay MON=newWeekDay() { @Override public WeekDay nextDay() { return SUN; } }; public abstractWeekDay nextDay(); { } /* public WeekDay nextDay() { if(this==SUN) return MON; else { return SUN; } }*/ @Override public String toString() { returnthis==SUN?"SUN":"MON"; } }
package com.itcast.day1; public class EnumTest{ public staticvoid main(String[] args) { WeekDayweekDay=WeekDay.MON; System.out.println(weekDay.nextDay());//SUN }}
java的枚举的基本应用
public class EnumTest{ public static void main(String[] args) { WeekDay1 weekDay=WeekDay1.MON; System.out.println(weekDay.nextDay());//SUN WeekDay weekDay2=WeekDay.FRI;//自动将枚举转换成string System.out.println(weekDay2);//FRI System.out.println(weekDay2.name());//FRI System.out.println(weekDay2.ordinal());//排行 第5 System.out.println(WeekDay.valueOf("SUN"));//将字符串SUN转换成对象 System.out.println(WeekDay.values().length);//得到这个枚举数组的长度 76 } //定义枚举 public enum WeekDay { SUN,MON,TUE,WED,THI,FRI,SAT; }}
实现带有构造方法的枚举
枚举也是一个类
package com.itcast.day1; public class EnumTest{ public staticvoid main(String[] args) { WeekDay1weekDay=WeekDay1.MON; System.out.println(weekDay.nextDay());//SUN WeekDayweekDay2=WeekDay.FRI;//自动将枚举转换成string System.out.println(weekDay2);//FRI System.out.println(weekDay2.name());//FRI System.out.println(weekDay2.ordinal());//排行 第5 System.out.println(WeekDay.valueOf("SUN"));//将字符串SUN转换成对象 System.out.println(WeekDay.values().length);//得到这个枚举数组的长度 76 } //定义枚举 public enumWeekDay { // SUN,MON,TUE,WED,THI,FRI,SAT;//元素列表必须定义在最前面 SUN(1),MON,TUE,WED,THI,FRI,SAT;//SUN(1) 加参数列表 调用有参数的构造参数 //MON() 表示调用默认的构造方法 //构造方法必须定义在元素列表后面 privateWeekDay() { System.out.println("first"); } privateWeekDay(int day) { System.out.println("secod"); } }}
实现带有抽象方法的枚举
枚举只有一个成员时,就可以作为一种单例的实现方式
package com.itcast.day1; import java.util.Date; public class EnumTest{ public staticvoid main(String[] args) { WeekDay1weekDay=WeekDay1.MON; System.out.println(weekDay.nextDay());//SUN WeekDayweekDay2=WeekDay.FRI;//自动将枚举转换成string System.out.println(weekDay2);//FRI System.out.println(weekDay2.name());//FRI System.out.println(weekDay2.ordinal());//排行 第5 System.out.println(WeekDay.valueOf("SUN"));//将字符串SUN转换成对象 System.out.println(WeekDay.values().length);//得到这个枚举数组的长度 76 } //定义枚举 public enumWeekDay { // SUN,MON,TUE,WED,THI,FRI,SAT;//元素列表必须定义在最前面 SUN(1),MON,TUE,WED,THI,FRI,SAT;//SUN(1) 加参数列表 调用有参数的构造参数 //MON() 表示调用默认的构造方法 //构造方法必须定义在元素列表后面 privateWeekDay() { System.out.println("first"); } privateWeekDay(int day) { System.out.println("secod"); } }
//交通灯,带上抽象方法的枚举
透彻分析反射的基础_Class类
反射的基石—> Class类
1. java程序中的各个JAVA类属于同一事物,描述这类事物到的JAVA类名就是Class
2. 对比提问:众多的人用什么类表示?众多的JAVA类用什么表示?
人-> Person
JAVA类->Class
3. 对比提问:Person类代表人,它的实例对象就是张三,李四这样一个个具体的人,Class代表Java类,它的各个实例对象又分别是什么呢?
1. 对应各个类在内存中的字节码。例如Person类的字节码,ArrayList类的字节码,等等
2. 一个类被加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类字节码是不同的,所以他们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象来
如何得到各个字节码对应的实例对象(Class类型)
1. 类名.class,例如,System.class
2. 对象.getClass(),例如,new Date().getClass();
3. Class.foName(“类名”);,例如,Class.forName(“java.util.Date”);
9个预定义Class实例对象:
1. 查看Class.isPrimlative方法的帮助
2. Int.claas==Integer.class fales
package com.itcast.day1;
public class ReflectTest
{
public staticvoid main(String[] args) throws Exception
{
Stringstr1="abc1";
Classclsl=str1.getClass();
Classcls2=String.class;
Classcls3=Class.forName("java.lang.String");
System.out.println(clsl==cls2);//true
System.out.println(clsl==cls3);//true
System.out.println(clsl.isPrimitive());//false不是基本类型
System.out.println(int.class==Integer.class);//false
System.out.println(int.class==Integer.TYPE);//true
System.out.println(int[].class.isArray());//true
//数组类型的class实例对象用class.isArray()
//总之,只要是在源程序出现的类型都有各自的的Class实例对象,如int[],void
}
}
public enumTrafficLamp { //相等于new子类的实例对象,并且调用父类的有参数的构造方法 RED(30){ @Override public TrafficLamp nextLamp() { //红灯以后返回绿灯 return GREEN; } }, GREEN(45){ @Override public TrafficLamp nextLamp() { //绿灯以后黄 return YELLOW; } }, YELLOW(5){ @Override public TrafficLamp nextLamp() { //黄灯以后红灯 return RED; } }; publicabstract TrafficLamp nextLamp(); privateint time;//每个灯都拥有自己的时间 privateTrafficLamp(int time) { this.time=time; } }}
理解反射的概念
反射
1. 反射就是把Java类中的各种成分映射成相应的的java类。例如,一个java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等信息也用一个个的Jvaa类来表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类,表示java类的Class类显然要提供一系列的方法,来获取其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应的类的实例对象来表示,他们的Field,Method,Contructor,Package等等
2. 一个类中的每个成员都可以用到相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象后,得到这些实例后怎么用?
构造方法的反射应用
Constructor类
1. Constructor类代表某个类中的一个构造方法
2. 得到某个类的所有构造方法
例子:Constructor construtors[]=Class.forName(“java.lang.String”).getConstrutors();
3. 得到某一个构造方法:
例子: Constructors constructors=Class.forName(“java.lang.String”).getContstructor(StringBuffer.class);
//获得方法是要用到的类型
4. 创建实例对象
1. 通常方式:String str=new String(new StringBufferf(“abc”));
2. 反射方式:String str=(Strtring)constructor.newInstance(new StringBuffer(“abc”));
//调用方法时要用到上面相同的类型的实例对象
5. Class.newInstance()方法
例子:String obj=(String)Classs.forName(“java.lang.String”).newInstance();
该方法内部先得到默认的构造方法,然后该构造方法创建实例对象
该方法内部的具体代码是怎样写的呢?用到了缓冲机制来保存默认的构造方法的实例对象
public staticvoid main(String[] args) throws Exception { String.class.getConstructor(StringBuffer.class);//值接受一个参数的的构造方法 String str2=new String(newStringBuffer("jj")); // Constructorconstructor=String.class.getConstructor(StringBuffer.class) Constructorconstructor=Class.forName("java.lang.String").getConstructor(StringBuffer.class); String str3=(String)constructor.newInstance(newStringBuffer("aaa")); }
成员变量的反射
Field类
1. Field类代表某个类中的一个成员变量
2. 演示用eclipse自动生成Java类的构造方法
3. 问题:得到的Field都系是对应到类上面的成员变量,还是对应到对象上的成员变量?类只有一个,而该类的实例对象有多个,如果是与对象关联,哪关联的是哪个对象呢?所以字段fieldX代表的是X的定义,而不是具体的X变量
实例代码:
public class ReflectPoint{ private intx; public inty; public ReflectPoint(int x, int y) { super(); this.x = x; this.y = y; } } package com.itcast.day1; import java.lang.reflect.*; public class ReflectTest{ public staticvoid main(String[] args) throws Exception { ReflectPoint fp=new ReflectPoint(3,5); Field fieldY=fp.getClass().getField("y");//代表变量,不代表值 System.out.println(fieldY); System.out.println(fieldY.get(fp));//从那个对象上取出y //对于私有属性:设置可见----->设置可以访问 FieldfieldX=fp.getClass().getDeclaredField("x");//面对私有的变量,看不见,就用声明的字段方法获取 fieldX.setAccessible(true);//暴力反射,不管对方同意不?设置可以可以访问 System.out.println(fieldX.get(fp)); }}
成员变量反射的综合案例
作业:将任意一个对象中的所有String类型的成员变量所对应的字符串内容的”b“改成”a”;
package com.itcast.day1; public class ReflectPoint{ private intx; public inty; 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; } @Override public String toString() { return str1+":"+str2+":"+str3; } }
package com.itcast.day1; import java.io.File;import java.lang.reflect.Constructor;import java.lang.reflect.Field; public class ReflectTest{ public staticvoid main(String[] args) throws Exception { changeStringValue(fp); System.out.println(fp);//aall:aasketaall:itcast } private staticvoid changeStringValue(Object obj) throws Exception { Field[]fields=obj.getClass().getFields(); for(Field field:fields) { if(field.getType()==String.class) { StringoldValue=(String) field.get(obj); StringnewValue=oldValue.replace('b','a');//替换 field.set(obj,newValue);//设置对象上的那个值 } } } }
成员方法的反射
Method类
1. Method类代表某个类中的一个成员方法
2. 得到类中的某一个方法:
例子:
Method charAt=Class.forName(“java.lang.String”).getMethod(“charAt”,int.class);
3. 调用方法:
通常方式:System.out.println(str.charAt(1));
反射方式:System.out.println(charAt.invoke(str,1));
如果传递给Method对象的invoke()方法的一个参数为null,这有着什么样的意义呢?说明该Method对象对应的是一个静态方法!
4. jdk1.4和jdk1.5的invoke方法的区别
jdk1.5:public Object invoke(Object obj,Object…args)
Jdk1.4: publicObject invoke(Object obj,Object[] args),即按照jdk1.4的语法
需要将与各数组作为参数传递给invoke方法时,数组中的每个元素分别对应被
public static void main(String[] args) throws Exception { Stringstr1="abc1"; //调用str1.charAt(1); Method methodCharAt=String.class.getMethod("charAt",int.class); System.out.println(methodCharAt.invoke(str1,1));//调用charAt方法,此得到b //methodCharAt.invoke(null,1) 调用静态方法,对象为null System.out.println(methodCharAt.invoke(str1,new Integer[]{2}));//jdk.1.4调用方式 }
对接收数组参数的成员方法进行反射
用反射的方式执行某个类中的main方法
1. 目标:
写一个程序,这个程序能够根据用户提供的类名,去执行类中的main方法
普通方式调用完后,
2. 问题
启动java程序的main方法参数是一个字符串数组,即public static void main(String[] args),通过反射的方式来刁永红这个main方法时,如果和为invoke方法传递参数呢?按jdk1.5的语法,整个数组是一个参数,而按jdk1.4的语法,数组中的每个元素对应一个参数,当把一个字符串作为参数传递给invoke方法时,javac会到底按照那种语法进行执行呢?jdk1.5版本肯定要兼容jdk1.4的语法,会按照jdk1.4的语法进行处理,即把数组打散成为若干个单独的参数。所以,在给main方法传递参数时,不能使用代码mianMethod.invoke(null,new String[]{“xxx”}),javac只能把它的那个在jdk1.4的语法进行理解,而不把它当做jdk1.5的预付解释,因此会出现参数类型不对的问题
5. 解决办法:
mainMethod.invoke(null,new Object[]{new String{“xxx”}});
mainMethod.invoke(null,(Object)new String[]{“xxx”});,编译器会做特殊处理,编译时不会把参数当做数组看待,也就不会进数组打散成若干参数了
package com.itcast.day1; import java.io.File;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method; public class ReflectTest{ public static void main(String[] args) throws Exception { //TestArguments.main(new String[]{"acb","hhf","jdj"}); //用反射的方式调用 String startingClassName=args[0]; MethodmainMethod=Class.forName(startingClassName).getMethod("main",String[].class); //现将字符串打包成一个Object对象数组的第一个对象 mainMethod.invoke(null, new Object[]{newString[]{"acb","hhf","jdj"}}); //或者 // mainMethod.invoke(null,(Object)newString[]{"acb","hhf","jdj"}); } privatestatic void changeStringValue(Object obj) throws Exception { Field[]fields=obj.getClass().getFields(); for(Fieldfield:fields) { if(field.getType()==String.class) { StringoldValue=(String) field.get(obj); StringnewValue=oldValue.replace('b','a');//替换 field.set(obj,newValue);//设置对象上的那个值 } } } }class TestArguments{ publicstatic void main(String[] args) { for(Stringarg:args) { System.out.println(arg); } }}
数组与Object的关系及其反射类型
数组(具有相同的元素类型,和相同的纬度)的字节码是同一个对象
int[] a1=newint[]{1,2,3}; int[]a2=new int[4]; int[][]a3=new int[2][3]; String[] a4=newString[]{"a","b","c"}; System.out.println(a1.getClass()==a2.getClass());//true //System.out.println(a1.getClass()==a4.getClass());//报错 System.out.println(a1.getClass().getName());//[I 表示数组 整数 System.out.println(a1.getClass().getSuperclass());//class java.lang.Object System.out.println(a1.getClass().getSuperclass().getName());/*父类名 java.lang.Object*/ Object obj1=a1; Object obj2=a4; // Object[] obj3=a1;不能转换 Object[] obj4=a3; Object[] obj5=a4; System.out.println(a1);//[I@43ef9157 System.out.println(Arrays.asList(a1));//[[I@331f2ee1] System.out.println(Arrays.asList(a4));//[a, b, c]
数组的反射应用
数组的反射
1. 具有相同的纬度和元素类型的数组属于同一个类型,即具有相同的Class实例对象
2. 代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class
3. 基本类型的一维数组可以被当做Objetc类型使用,不能当做Objetc[] 类型使用;非基本类型的一维数组,即可以当做Object类型的使用,又可以当做Object[]类型使用
4. Arrays.asList()方法处理int[]和String[]时的差异
5. Array工具类用于完成对数组的反射操作
思考题:怎么得到数组的元素类型?没办法
public staticvoid main(String[] args) throws Exception {String[] aa=new String[]{"a","b","c"}; Object obj=aa; printObject(obj); printObject("jjd"); } private staticvoid printObject(Object obj) { Classclasszz=obj.getClass(); if(classzz.isArray())//是数组 { int len=Array.getLength(obj);//得到长度 for(inti=0;i<len;i++) { System.out.println(Array.get(classzz, i)); } } else { System.out.println(obj); } }
- 黑马程序员_JAVA_枚举和反射总结
- 黑马程序员_java_反射总结
- 黑马程序员_Java_反射机制总结
- 黑马程序员_Java_枚举
- 黑马程序员_Java_反射
- 黑马程序员_JAVA_反射
- 黑马程序员_Java_反射
- 黑马程序员_Java_反射
- 黑马程序员_Java_反射
- 黑马程序员_JAVA_反射
- 黑马程序员_JAVA_反射
- 黑马程序员_java_反射
- 黑马程序员_Java_反射
- 黑马程序员_Java_反射
- 黑马程序员_Java_枚举(enum)
- 黑马程序员_Java_集合总结
- 黑马程序员_Java_多线程总结
- 黑马程序员_Java_集合总结
- 有关qsort函数的部分讲解
- Mysql的常用数据类型以及用途总结
- Git远程操作详解
- 黑马程序员——学习日志8集合
- 【黑马程序员】交通灯管理系统
- 黑马程序员_JAVA_枚举和反射总结
- OR1200数据Cache介绍
- 线上进行调整,不至于像以前一样经历退货和返工的麻烦。对于标准产品满足不同客户的多样需求,是营销理念上的进步
- Android学习系列(18)--App工程结构搭建
- 进程保护
- Advanced Programming in MATLAB 高级matlab程序设计
- 使用batch insert解决MySQL的insert吞吐量问题 - billy鹏
- Oracle DBA的神器: PRM恢复工具,可脱离Oracle软件运行,直接读取Oracle数据文件中的数据
- 黑马程序员——学习日志9IO流