获取属性:
Field getField(String name)
返回一个 Field对象反映的类或接口的 类对象表示的指定公共成员。
Field[] getFields()
返回一个数组包含 Field物体反射的类或接口的 类对象代表所有可访问的公共领域。
Field getDeclaredField(String name)
返回一个对象,反映了 Field指定声明字段的类或接口的 类对象表示。
Field[] getDeclaredFields()
返回 Field物体反射所有字段的类或接口的 类对象表示声明数组。
Field
方法:
Object get(Object obj)
返回的 Field表示字段的值,指定对象上。
获取方法:
方法
getMethod(String name, 类<?>… parameterTypes)
返回一个 方法对象反映的类或接口的 类对象表示的指定公共成员方法。
方法[]getMethods()
返回一个数组包含 方法物体反射所有的类或接口的 类对象表示的公共方法,包括那些由类或接口的超类和超接口继承的声明。
方法 getDeclaredMethod(String name, 类<?>… parameterTypes)
返回一个 方法对象反映指定声明方法的类或接口的 类对象表示。
方法[] getDeclaredMethods()
返回一个数组包含 方法物体反射所有声明的方法的类或接口的 类对象,代表包括公众、保护,默认(包)的访问,和私有方法,但不包括继承的方法。
Method
方法:
Object invoke(Object obj, Object… args)
调用底层的方法,这 方法对象表示,对指定对象的指定参数。
类<?>getReturnType()
返回一个 类表示这 方法对象表示法的形式返回类型。
案例一:
ArrayList list = new ArrayList()
能不能在list中添加一个字符串数据
案例二:
//pet.properties文件内容
pet=cn.ppenggs.reflect.exer.Dog
name=小白
age=5
gender=公
method=eat
package cn.ppenggs.reflect.exer;
public interface Pet {
public void eat();
public void play();
}
package cn.ppenggs.reflect.exer;
public class Dog implements Pet {
private String name;
private int age;
private char gender;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public void eat(){
System.out.println("dog吃");
}
public void play(){
System.out.println("dog玩");
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
", gender=" + gender +
'}';
}
}
package cn.ppenggs.reflect.exer;
public class Cat implements Pet{
private String name;
private int age;
private char gender;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public void eat(){
System.out.println("cat吃");
}
public void play(){
System.out.println("cat玩");
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
", gender=" + gender +
'}';
}
}
package cn.ppenggs.reflect.exer;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
//读取properties
Properties properties = new Properties();
//加载文件pet.properties文件的内容到properties中
properties.load(new FileInputStream("D:\\Day\\pet.properties"));
//获取properties中pet key对应的值
String value = properties.getProperty("pet");
//根据配置文件中的全路径名称,可以创建该类的class对象
Class clz = Class.forName(value);
//创建对象
Object object = clz.newInstance();
//获取配置文件中属性的值
String name = properties.getProperty("name");
String age = properties.getProperty("age");
String gender = properties.getProperty("gender");
//1、通过反射获取属性,暴力破解 赋值
//获取name属性
Field fname =clz.getDeclaredField("name");
fname.setAccessible(true);
fname.set(object,name);
//获取age属性
Field fage =clz.getDeclaredField("age");
fage.setAccessible(true);
fage.set(object,Integer.parseInt(age));
//获取gender属性
Field fgender =clz.getDeclaredField("gender");
fgender.setAccessible(true);
fgender.set(object,gender.charAt(0));
//调用方法method
String method = properties.getProperty("method");
//通过反射调用方法
Method m = clz.getMethod(method);
m.invoke(object);
System.out.println(object);
}
}
反射的优缺点
优点:
1、提高了代码的灵活性
2、提高了扩展性
缺点:
1、可以绕过泛型的检查,可能会导致集合的使用出问题
2、打破了面向对象封装
JDK1.5
静态导入:
枚举:
如果数据相对比较固定
星期一到星期日
一年的月份12个月
定义枚举类
格式:
enum 枚举名称
可以在枚举中,定义常量
常量1,常量2,常量3,常量4
注意:
1、枚举常亮只能放在首行,如果出现分号,则代表枚举常量定义结束
2、枚举常量最后可以加分号也可以不加分号
3、枚举可以保证枚举常量定义是的顺序
4、枚举本质是个类,但是该类不能通过new创建对象
5、枚举中可以定义属性,定义方法,定义构造方法(不能用public,一般使用private),但是不能放在枚举常量的前边来定义
6、枚举类不能再集成父类,可以实现接口(每个枚举常量可以分别实现接口中的方法)
package cn.ppenggs.enumx;
public class EnumDemo {
public static void main(String[] args) {
Week w = Week.Friday;
Week[] weeks = Week.values();
for (Week ws: weeks) {
System.out.println(ws.name());
}
}
}
//定义枚举表示星期
enum Week{
Sunday, Monday,Tuesday,Wednesday,Thursday,Friday,Saturday;
public int num;
public void method(){}
private Week(){}
}
Swich(值) case:
int(byte char short) JDK1.7支持String
JDK1.5支持枚举
案例演示:枚举在Switch case中的应用
package cn.tedu.enumx;
public class EnumDemo3 {
public static void main(String[] args) {
Week1 w = Week1.星期六;
switch (w){
case 星期一:
System.out.println("星期一上班");
break;
case 星期二:
System.out.println("上班");
break;
case 星期三:
System.out.println("上班");
break;
case 星期六:
System.out.println("休息");
}
}
}
enum Week1{
星期日,星期一,星期二,星期三,星期四,星期五,星期六
}
可变参数:
在方法的参数列表,可以通过定义可变参数从而实现方法的参数个数由调用者确定
格式:
数据类型…arr:可变参数
注意:
1、方法参数列表中可以定义多个可变参数吗?不可以,只能定义一个可变参数
2、方法参数列表中可以同时定义单个参数和可变参数,但是可变参数必须放到参数列表的最后
优点:
简化了代码,提高了代码的复用性
提高了代码的灵活性
public static void main(String[] args) {
System.out.println(add(3,5));
System.out.println(add(2,3,4));
int[] arr = new int[]{1,2,3,4,5};
System.out.println(add(arr));
add();
}
public static int add(int... arr){
int sum = 0;
for(int i :arr){
sum+=i;
}
return sum;
}
JDK1.8:
接口中可以定义非抽象方法
格式:
在方法声明上加上default或是static
如果加上default,则该接口的实现类可以直接调用该方法
如果加上static,则可以通过接口.方法名直接调用
接口和抽象类的区别?
从jdk1.8开始,接口中也可以定义带有方法体的方法
Lamdba:
函数式编程:Scala