枚举:枚举是一种特殊的类,其中的每个元素都是该类的一个实例对象
枚举可以让编译器在编译时就可以控制源程序中填写的非法值
枚举就相当于一个类,其中也可以定义构造方法、成员变量、普通方法和抽象方法
枚举元素必须位于枚举体中的最开始部分,枚举元素列表的后要有分号与其他成员分隔
把枚举中的成员方法或变量等放在枚举元素的前面,编译器报告错误
枚举只有一个成员时,就可以作为一种单例的实现方式
class Test{
public static void main(String[] args){
WeekDay w=WeekDay.SUN; //WeekDay所能取得的值只能是类中所定义的那几个常量
w.print();
}
}
//模拟枚举
abstract class WeekDay{
//私有化构造函数,无法实例化
private WeekDay(){}
//利用匿名内部类来创建对象,匿名内部类是唯一一种无构造方法的类
public static final WeekDay SUN=new WeekDay(){ //注意:这是在WeekDay类的内部来创建内部类,private是不起作用的
//private只能说相对于不是We ekDay类的外部来创建时才起作用
//覆盖抽象方法
public void print(){
System.out.println("今天是星期天,明天是星期一");
}
};
public static final WeekDay MON=new WeekDay(){
public void print(){
System.out.println("今天是星期一,明天星期二");
}
};
public static final WeekDay TUE=new WeekDay(){
public void print(){
System.out.println("今天是星期二,明天星期三");
}
};
public static final WeekDay WED=new WeekDay(){
public void print(){
System.out.println("今天是星期三,明天星期四");
}
};
public static final WeekDay THI=new WeekDay(){
public void print(){
System.out.println("今天是星期四,明天星期五");
}
};
public static final WeekDay FRI=new WeekDay(){
public void print(){
System.out.println("今天是星期五,明天星期六");
}
};
public static final WeekDay SAT=new WeekDay(){
public void print(){
System.out.println("今天是星期六,明天是星期日");
}
};
//定义抽象方法
public abstract void print();
}
//枚举练习
class EnumTest{
public static void main(String[] args){
WeekDay wd=WeekDay.SUN;
System.out.println(wd.nextDay());
}
}
//定义枚举,枚举相于一个类
enum WeekDay{
//枚举中的元素位于枚举中的开始的地方,否则编译不通过
SUN{//实现抽象方法,相当于创建了一个内部类
public String nextDay(){
return "monday";
}
},MON{
public String nextDay(){
return "tuesday";
}
},TUE{
public String nextDay(){
return "wednesday";
}
},WEN{
public String nextDay(){
return "thursday";
}
},THU{
public String nextDay(){
return "friday";
}
},FRI{
public String nextDay(){
return "saturday";
}
},SAT{
public String nextDay(){
return "sunday";
}
};
//定义枚举构造函数
WeekDay(){
System.out.println("枚举的构造函数");
}
//定义方法
public abstract String nextDay();
}
可变参数:一个方法接受的参数个数不固定
特点:
只能出现在参数列表的最后;
...位于变量类型和变量名之间,前后有无空格都可以;
调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数
增强for循环:
语法:for ( type 变量名:集合变量名 ) { … }
注意事项:
迭代变量必须在( )中定义
集合变量可以是数组或实现了Iterable接口的集合类
class EnhanceFor{
public static void main(String[] args){
int sum=add(2,3,4,5);
System.out.println("sum="+sum);
}
//可变参数位于参数列表的最后面
public static int add(int x,int...args){
int sum=x;
//参数存储于一个数组中
for(int i:args){//集合变量可以是数组或实现了Itreator接口的集合类
sum=sum+i;
}
return sum;
}
}
反射技术
反射就是把Java类中的各种成分映射成相应的java类
一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等
信息也用一个个的Java类来表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。
表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息
这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等
常用方法:
static Class<?> forName(String className):返回与带有给定字符串名的类或接口相关联的 Class 对象
Constructor<T> getConstructor(Class<?>... parameterTypes) :返回某个公共构造函数
Constructor<?>[] getConstructors():返回所有公共的构造函数
Method getMethod(String name, Class<?>... parameterTypes):返回某个公共方法
Method[] getMethods():返回所有公共方法
Field getField(String name):返回某个公共的字段
Field[] getFields():返回所有的公共字段
String getName():以String 的形式返回此 Class 对象所表示的实体名称
T newInstance(): 创建此 Class 对象所表示的类的一个新实例
import java.lang.reflect.*;
class Person{
private String name;
public int age;
public Person(){}
public Person(String name,int age){
this.name=name;
this.age=age;
}
private void getName(){
System.out.println("name="+name);
}
public void print(){
System.out.println("name="+name+" age="+age);
}
}
class ReflectTest{
public static void main(String[] args) throws Exception{
Person p=new Person("lidaofu",24);
//得到class文件的第一种方式
//Class c=p.getClass();
//得到class文件的第二种方式
//Class c2=Class.forName("Person");
/*参数中要是类的全名(包名+类名)
//Class s=Class.forName("java.lang.String");
//返回类的公共构造函数(即被public所修饰的类)
Constructor[] constructor=c2.getConstructors();
for(int i=0;i<constructor.length;i++){
System.out.println(constructor[i].getName());
}
//返回某个指定的构造函数
Constructor con=c2.getConstructor(String.class,int.class);
//返回类中的公共方法,私有,默认,保护修饰的方法都不会被获取
Method[] methods=c2.getMethods();
for(int i=0;i<methods.length;i++)
System.out.println(methods[i].getName());
//返回类中的某个公共方法
Method method=c2.getMethod("print");//要写上方法名和方法中的参数类型的class,如果方法为空参数则不写
//返回类中所有的公共字段
Field[] fields=c2.getFields();
for(int i=0;i<fields.length;i++)
System.out.println(fields[i].getName());
//暴力获取类中的所有字段,包括私有的
Field field=c2.getDeclaredField("name");
*/
//利用Class创建一个新实例
Person p2=(Person)Class.forName("Person").newInstance();
//利用构造函数创建一个实例
Constructor con=Class.forName("Person").getConstructor(String.class,int.class);
Person p3=(Person)con.newInstance("李道福",24);
//利用反射来调用实例方法
Method method=Class.forName("Person").getMethod("print");
//invoke中的参数为调用对象,如果为null则表示该方法为静态方法
method.invoke(p3);
}
}
数组的反射:
1.具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象
2.代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class
3.基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维数组,
既可以当做Object类型使用,又可以当做Object[]类型使用
class Test{
public static void print(Integer[] arr){
for(Integer i:arr)
System.out.println("----"+i);
}
public static void print(int[] arg){
for(int i:arg)
System.out.println("===="+i);
}
}
class ReflectTest{
public static void main(String[] args)throws Exception{
/* Integer[] inr=new Integer[1];
//代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class
Class claxx=inr.getClass().getSuperclass();
System.o