目录
反射
什么是反射
反射API
动态加载类
Class.forName( )
动态创建对象
newInstance( )
动态调用方法
动态发现方法
动态执行方法
执行不可访问方法
日期操作
Date及其常用API
Java中的时间
Date类简介
setTime和getTime方法
Date重写toString
SimpleDateFormat
SimpleDateFormat简介
日期模式匹配字符
将Date格式化为String
将String格式化为Date
Calendar
Calendar简介
getInstance方法
设置日期及时间分量
获取日期及时间分量
getActualMaximum方法
add方法
setTime和getTime方法
Java8 Lambda
Lambda
Lambda表达式简介
Lambda表达式的结构
功能接口(函数接口)
@ FunctionalInterface
Lambda表达式与匿名内部类
反射是Java系统的API,它允许程序在运行过程中取得任何一个已知名称的类的内部信息,包括其中的构造方法、声明的字段和定义的方法等
利用反射API可以实现动态执行:
动态加载类,获取信息
-动态创建对象
动态访问属性
-动态调用方法
动态执行:只是在JVM运行期间才确定的执行次序。
静态执行:是指编译以后就确定了程序的运行次序, JVM运行期间按照既定的次序执行。
Java反射API提供了动态执行能力ClassAPI :
Java反射API位于java.lang.reflect包中。主要包括以下几类:
package reflect;
import java.lang.reflect.Method;
import java.util.Scanner;
/**
* java 反射机制
*
* 反射机制是一种动态机制,允许我们程序在运行期间确定实例化对象的操作,方法调用的操作和
* 属性赋值等操作。
*
* 反射可以大大提高代码灵活度,但是也会带来更多的系统开销和降低运行性能。因此反射只在关
* 键地方使用而不能过度依赖。
* @author pc
*
*/
public class ReflectDemo1 {
public static void main(String[] args) throws ClassNotFoundException {
/*
* Class类 称为:类的类对象
* 该类的每一个实例用于表示已经被JVM加载的一个类,并且每个被JVM加载的类都有
* 且只有一个类对象与之关联。
* 通过类对象我们可以得知其表示的类的一切信息:类名,有哪些属性,方法,构造器
* 并可以获取它们以便在运行期间调用。
*
* 所以反射的第一步就是获取要操作的类的类对象。
*
* 获取一个类的类对象有三种方式:
* 1:类名.class
* 例如:String.class
* ArrayList.class
*
* 2:Class.forName(String className)
* Class提供了一个静态方法forName,可以根据类的完全限定名(包名.类名)形式
* 获取该类的类对象
*
* 3:ClassLoader类加载器形式
*/
//获取String的类对象
// Class cls = String.class;//优点是简单直接,但是缺点是硬编码获取
/*
* 该方法会抛出ClassNotFoundException,当给定的类的完全限定名无效时会抛出
* 该异常。
*/
// Class> cls = Class.forName("java.lang.String");
// Class> cls = Class.forName("reflect.Person");
/*
* java.lang.String
* java.util.ArrayList
* java.util.HashSet
* java.util.HashMap
* java.io.FileOutputStream
* reflect.Person
* 以上可參考
*/
System.out.println("请输入一个类名:");
Scanner scanner = new Scanner(System.in);
String className = scanner.nextLine();
Class> cls = Class.forName(className);
//获取类名
String name = cls.getName();
System.out.println(name);
/*
* Method类的每一个实例用于表示某个类中的某个方法
*
* Class提供的方法:
* Method[] getMethods()
* 可以获取Class表示的类的所有公有方法
*/
System.out.println("获取本类所有公有方法,包含从超类继承的方法");
Method[] methods= cls.getMethods();
for(Method m : methods) {
System.out.println(m.getName());
}
System.out.println("获取本类定义的所有方法(不含有继承的方法):");
methods = cls.getDeclaredMethods();
for(Method m : methods) {
System.out.println(m.getName());
}
}
}
动态加载类到内存万法区:
Class cls = Class.forName(类名)
1.类名是运行期间动态输入的类名,可以任何类名
2.返回值是一个引用,利用这个引|用指向的对象可以访问方法区中的类信息。
3.如果类名是错误的将出现"类没有找到"的异常
Class提供了动态创建对象的方法:
Object newInstance( )
package reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
/**
* 使用反射机制实例化对象
* @author pc
*
*/
public class ReflectDemo2 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
//硬编码方式实例化
Person p = new Person();
System.out.println(p);
ArrayList a = new ArrayList();
System.out.println(a);
/*
* 使用反射机制:
* 1:加载要实例化对象的类的类对象
* 2:通过类对象的newInstance方法实例化
*/
//实例化Person
Class> cls = Class.forName("reflect.Person");
//需要注意newInstance方法要求Class表示的类必须有无参构造器
Object obj = cls.newInstance();
System.out.println(obj);
//硬编码方式调用有参数构造器
Student stu = new Student("张三",22);
System.out.println(stu);
/*
* 利用有参构造器实例化对象
* 1:加载要实例化的类的类对象
* 2:通过类对象获取指定的构造方法
* 3:利用该构造方法实例化
*/
//1
Class cls1 = Class.forName("reflect.Student");
//2 Student(String name, int age)
Constructor c = cls1.getConstructor(String.class,int.class);
Object o1 = c.newInstance("李四",18);
System.out.println(o1);
}
}
Class提供了方法可以动态获取类的全部方法信息:
Method[ getDeclaredMethods( )
Method提供了动态执行一个方法的方法:
Object invoke(Object obj, Object.. args)
package reflect;
import java.lang.reflect.Method;
import java.util.Scanner;
/**
* 利用反射调用方法
* @author pc
*
*/
public class ReflectDemo3 {
public static void main(String[] args) throws Exception {
Person p = new Person();
p.sayHello();
/*
* 利用反射调用方法:
* 1:加载类对象
* 2:实例化
* 3:通过类对象获取要调用的方法
* 4:调用该方法
*/
Scanner scanner = new Scanner(System.in);
System.out.println("请输入类名:");
String className = scanner.nextLine();
System.out.println("请输入方法名:");
String methodName = scanner.nextLine();
//1
// Class> cls = Class.forName("reflect.Person");
Class> cls = Class.forName(className);
//2 Person o = new Person();
Object o = cls.newInstance();
//3 获取Person中无参数的sayHello方法
// Method method = cls.getMethod("sayHello");
Method method = cls.getMethod(methodName);
//4 o.sayHello()
method.invoke(o);
}
}
如果利用反射API调用了没有可访问权限时候会抛出异常:
IllegalAccessException,表示没有访问权限。
但是在Method方法上提供了解除访问限制的方法:
setAccessible(boolean flag)
在invoke之前使用这个方法可以解除访问限制,实现访问没有权限的方法。
注意:这个功能破坏了面向对象原有的封装性,利用它但是却能写出一些特殊功能代码,有些面试官也将这个知识点作为反射是否熟悉的标志!
package reflect;
import java.lang.reflect.Method;
/**
* 使用反射机制调用私有方法
* 这样做可能破坏类的封装性
* @author pc
*
*/
public class ReflectDemo5 {
public static void main(String[] args) throws Exception {
// Person p = new Person();
// p.dosome();//编译不通过
Class> cls = Class.forName("reflect.Person");
Object o = cls.newInstance();
//获取私有方法dosome
Method m = cls.getDeclaredMethod("dosome");
m.setAccessible(true);//强行访问!
m.invoke(o);
}
}
Date date = new Date();
//系统当前的日期及时间信息
System.out.println(date);
// Sun Jan 06 11:52:55 CST 2013
long time = date.getTime);
//1970年1月1日至今的毫秒数
/**使用setTime和getTime设置及获取时间*/
public void testSetTime() {
Date date = new Date();
//输出当天此时此刻的日期和时间
System.out.println(date);
long time = date.getTime();
//增加一天所经历的毫秒数
time
+=
60 *
60
* 24 * 1000;
date. setTime(time);
//输出明天此时此刻的日期和时间
System.out.println(date);
/**
获取当前系统时间*/
public void testGetTime() {
Date date = new Date();
System.out.println(date);
//1970年1月1日零时距此刻的毫秒数
long time = date.getTime();
System.out.println(time);
java.text.SimpleDateFormat是一个以与语言环境有关的方式来格式化和解析日期的具体类。它允许进行格式化(日期->文本)、解析(文本->日期)和规范化
/**日期格式化*/
public void testFormat() {
SimpleDateFormat sdf = new SimpleDateFormat(' 'yy- MM-dd HH:mm:ss' );
Date date = new Date();
String dateStr = sdf.format(date);
System.out.println(dateStr);
}
/**和format方法相反, parse方法用于按照特定格式将表示时间
的字符串转换为Date对象*/
public void testParse() throws Exception {
String str = "2013-12-25";
SimpleDateFormat sdf = new SimpleDateFormat( "yyy-MM-dd");
Date date = sdf.parse(str);
System.out.println(date);
}
Calendar提供了一个类方法getInstance ,以获得此类型的一个通用的对象
Calendar的getInstance方法返回一个Calendar对象其日历字段已由当前日期和时间初始化
Calendar C = Calendar.getInstance(;
/**使用alendar及子类获取时间*/
public void testGetInstance() {
Calendar C = Calendar.getInstance(;
//输出Calendar对象所属的实际类型
System.out.println(c.getClass).getName();
// getTime方法返回对应的Date对象
System.out.println(c.getTime();
//创建GregorianCalendar对象
GregorianC alendar c1 = new Gregorian alendar(2013, Calendar.DECEMBER,25);
System.out.println(c1.getTime();
}
/**设置日期及分量*/
public void testSet() {
Calendar C = Calendar.getInstance();
c.set(C alendar.YEAR, 2014);
c.set(C alendar.MONTH, Calendar.DEC EMBER);
c.set(Calendar.DATE, 25);
System.out. println(c.getTime());
//Thu Dec 25 16:02:08 CST 2014
c.set(C alendar.DATE, 32);
System.out.println(c.getTime());
//Thu Jan 01 16:02:08 CST 2015
}
使用Calendar提供的get方法及- -些常量可以获取日期及时间分量
/**获取时间及分量*/
public void testGet() {
Calendar C = Calendar.getInstance();
C. set(C alendar.YEAR, 2014);
c.set(C alendar. MONTH, Calendar.DECEMBER);
C. set(Calendar.DATE, 25);
int dayOfWeek = c.get(Calendar.DAY_ OF_ _WEE K);
System.out.println(dayOfWeek);
//输出为5,表示周四,周日为每周的第1天.
}
int getActualMaximum ( int field )给定此Calenda的时间值,返回指定日历字段可能拥有的最大值,
例如:
int year = 2014;
Calendar C = Calendar.getInstance();
c.set(C alendar.YEAR, year);
c.set(C alendar.DATE, 1);
for (int month = Calendar.JANUARY;
month <= Calendar.DEC EMBER; month+ +)
C. set(C alendar.MONTH, month);
System.out.println(year +"年"
+(month+1)+"月: "
+ c.getActualMaximum (Calendar.DATE+ "天");
}
}
void add ( int field,int mount )为给定的时间分量的值加上给定的值,若给定的值为负数则是减去给定的值
/**输出一年后再减去3个月的日期*/
public void testAdd(){
Calendar calendar = Calendar.getInstance();
calendar.add(C alendar.YEAR, 1);/加一年
calendar.add(C alendar.MONTH, -3);//减3个月
System.out.println(" year:" + calendar.get( alendar.YEAR));
System.out.println(" month:" +(calendar.get(C alendar.MONTH)+ 1));
System.out.println(" day:" + calendar.get( alendar.DAY_ OF_ .MONTH));
}
/**.通过Date对象设置日期,在获取日期*/
public void testsetTimeAndGetTime(){
Calendar calendar = Calendar.getInstance();
Date date = new Date();
calendar.setTime(date);
date = calendar.getTime();
}
(inta,intb)->{returna+b;}
() -> System. out. println("Hello World");
(String s) -> { System . out. println(s); }
() -> 42
() -> { return 3.1415 } ;
//通过Lambda表达式创建Runnable接口的实例:
Runnabler = () -> System.out.printIn("hello world ");
//相当于匿名内部类创建Runnable接口的实例:
Runnabler = newRunnable(){
public void run({
System.out.println("hello world");
}
};
//当不指明函数式接口时,编译器会自动解释这种转化:
Thread t = new Thread(
() -> System.out.printn("hello world")
);
/**Java编译器根据构造器参数 new Thread(Runnable r)
推断整个Lambda表达式的类型是Runnable类型的*/
错误:
Unexpected @ FunctionalInterface annotation
@FunctionalInterface ^ WorkerInterface is not a functional
interface multiple
non-overriding abstract methods found in interface
WorkerInterface 1 error