java笔记1(策略、代理模式、枚举、反射、注解)
java笔记1(策略、代理模式、枚举、反射、注解)
一个简单策略模式示例的实现
1.策略模式的组成
2.策略模式的实现
3.策略械的编写步骤
注:java中的Collections 就是策略模式的一个实现, 其中的很多方法通过传入不同的比较器,实现不同形式的比较。
4.定义一个实体类
package com.vvvv.strategy;
public class Person{
private int id;
private String name;
private int age;
…………get/set方法…………
}
5.定义策略接口
package com.vvvv.strategy;
import java.util.List;
public interface SortInterface{
public void sort(List<Person> list);
}
6.具体的策略类
1.根据名字升序
package com.vvvv.strategy;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class UpNameSort implements SortInterface, Comparator<Person>{
public void sort(List<Person> list) {
Collections.sort(list, this);
}
public int compare(Person o1, Person o2){
int result = o1.getName().compareTo(o2.getName());
if(0 == result) {
return o1.getId() - o2.getId();
}
return result;
}
}
2.根据名字降序
package com.vvvv.strategy;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class DownNameSort implements SortInterface, Comparator<Person>{
public void sort(List<Person> list) {
Collections.sort(list, this);
}
public int compare(Person o1, Person o2) {
int result = o2.getName().compareTo(o1.getName());
if(0 == result) {
return o1.getId() - o2.getId();
}
return result;
}
}
7.应用的环境类
package com.vvvv.strategy;
import java.util.List;
public class Environment{
private SortInterface sortInterface;
public Environment(SortInterface sortInterface){
this.sortInterface = sortInterface;
}
public Environment()
}
public void setSortInterface(SortInterface sortInterface){
this.sortInterface = sortInterface;
}
public void sort(List<Person> list){
this.sortInterface.sort(list);
}
}
8.客户端的调用
package com.vvvv.strategy;
import java.util.ArrayList;
import java.util.List;
public class Client{
public static void main(String[] args) {
Person p1 = new Person();
p1.setName("Tom");
p1.setId(1);
p1.setAge(20);
Person p2 = new Person();
p2.setName("Tonny");
p2.setId(2);
p2.setAge(50);
Person p3 = new Person();
p3.setName("Tom");
p3.setId(5);
p3.setAge(30);
Person p4 = new Person();
p4.setName("ABC");
p4.setId(8);
p4.setAge(10);
Person p5 = new Person();
p5.setName("Xyz");
p5.setId(9);
p5.setAge(15);
List<Person> list = new ArrayList<Person>();
list.add(p1);
list.add(p2);
list.add(p3);
list.add(p4);
list.add(p5);
Environment env = new Environment();
UpNameSort uns = new UpNameSort();
env.setSortInterface(uns);
env.sort(list);
for (int i = 0; i < list.size(); i++){
Person p = list.get(i);
System.out.println("id: " + p.getId() + ", name: " + p.getName()
+ ", age:" + p.getAge());
}
System.out.println("--------------");
DownNameSort dns = new DownNameSort();
env.setSortInterface(dns);
env.sort(list);
for (int i = 0; i < list.size(); i++){
Person p = list.get(i);
System.out.println("id: " + p.getId() + ", name: " + p.getName()
+ ", age:" + p.getAge());
}
}
}
枚举类型
1.枚举的每一个成员就是它一个实例,编译时确定
package com.vvvv.jdk5;
public enum Coin{
penny("hello"), nickel("world"), dime("welcome"), quarter("hello world");
private String value;
public String getValue(){
return value;
}
Coin(String value) {
this.value = value;
}
public static void main(String[] args) {
Coin coin = Coin.quarter;
System.out.println(coin.getValue());
}
}
2.构造EnumMap
package com.vvvv.jdk5;
import java.util.EnumMap;
import java.util.Map;
public class EnumMapDemo{
public static void main(String[] args) {
Map<Action, String> map = new EnumMap<Action, String>(Action.class);
map.put(Action.TURN_RIGHT, "向右转");
map.put(Action.SHOOT, "射击");
map.put(Action.TURN_LEFT, "向左转");
for (Action action : Action.values()){
System.out.println(map.get(action));
}
}
}
enum Action{
TURN_LEFT, TURN_RIGHT, SHO
}
3.构造EnumSet
package com.vvvv.jdk5;
import java.util.EnumSet;
import java.util.Iterator;
public class EnumSetDemo2{
public static void main(String[] args) {
EnumSet<FontConstant> enumSet = EnumSet.noneOf(FontConstant.class);
enumSet.add(FontConstant.Bold);
enumSet.add(FontConstant.Italilc);
showEnumSet(enumSet);
}
public static void showEnumSet(EnumSet<FontConstant> enumSet) {
for(Iterator<FontConstant> iter = enumSet.iterator(); iter.hasNext();){
System.out.println(iter.next());
}
}
}
4.构造EnumList
package com.vvvv.jdk5;
import java.util.EnumSet;
import java.util.Iterator;
public class EnumSetDemo2{
public static void main(String[] args) {
EnumSet<FontConstant> enumSet = EnumSet.noneOf(FontConstant.class);
enumSet.add(FontConstant.Bold);
enumSet.add(FontConstant.Italilc);
showEnumSet(enumSet);
}
public static void showEnumSet(EnumSet<FontConstant> enumSet) {
for(Iterator<FontConstant> iter = enumSet.iterator(); iter.hasNext();){
System.out.println(iter.next());
}
}
}
反射
1.使用forName
package com.vvvv.reflect;
import java.lang.reflect.Method;
public class DumpMethods{
public static void main(String[] args) throws Exception{
Class<?> classType = Class.forName(args[0]);
Method[] methods = classType.getDeclaredMethods();
for(Method method : methods) {
System.out.println(method);
}
}
}
2.使用.class语法
package com.vvvv.reflect;
import java.lang.reflect.Method;
public class InvokeTester{
public int add(int param1, int param2) {
return param1 + param2;
}
public String echo(String message) {
return "hello: " + message;
}
public static void main(String[] args) throws Exception{
// InvokeTester test = new InvokeTester();
// System.out.println(test.add(1, 2));
// System.out.println(test.echo("tom"));
Class<?> classType = InvokeTester.class;
Object invokeTester = classType.newInstance();
// System.out.println(invokeTester instanceof InvokeTester);
Method addMethod = classType.getMethod("add",new Class[]{int.class,
int.class});
Object result = addMethod.invoke(invokeTester,new Object[]{1,2});
System.out.println((Integer)result);
System.out.println("---------------------");
Method echoMethod = classType.getMethod("echo", new Class[]{String.class});
Object result2 = echoMethod.invoke(invokeTester, new Object[]{"tom"});
System.out.println((String)result2);
}
}
3.利用反射实现对象的拷贝
package com.vvvv.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectTester{
// 该方法实现对Customer对象的拷贝操作
public Object copy(Object object) throws Exception{
Class<?> classType = object.getClass();
Object objectCopy = classType.getConstructor(new Class[] {}).newInstance(new Object[] {});
// 获得对象的所有成员变量
Field[] fields = classType.getDeclaredFields();
for (Field field : fields) {
String name = field.getName();
String firstLetter = name.substring(0, 1).toUpperCase();// 将属性的首字母转换为大写
String getMethodName = "get" + firstLetter + name.substring(1);
String setMethodName = "set" + firstLetter + name.substring(1);
Method getMethod = classType.getMethod(getMethodName, new Class[] {});
Method setMethod = classType.getMethod(setMethodName, new Class[] { field.getType() });
Object value = getMethod.invoke(object, new Object[] {});
setMethod.invoke(objectCopy, new Object[] { value });
}
// 以上两行代码等价于下面一行
// Object obj2 = classType.newInstance();
// System.out.println(obj);
return objectCopy;
}
public static void main(String[] args) throws Exception{
Customer customer = new Customer("Tom", 20);
customer.setId(1L);
ReflectTester test = new ReflectTester();
Customer customer2 = (Customer) test.copy(customer);
System.out.println(customer2.getId() + "," + customer2.getName() + ","
+ customer2.getAge());
}
}
class Customer{
private Long id;
private String name;
private int age;
public Customer(){
}
public Customer(String name, int age) {
this.name = name;
this.age = age;
}
…………set 、get方法…………
}
4.创建数组
示例1:
package com.vvvv.reflect;
import java.lang.reflect.Array;
public class ArrayTester1{
public static void main(String[] args) throws Exception{
Class<?> classType = Class.forName("java.lang.String");
//创建一个数组长度为10的数组
Object array = Array.newInstance(classType, 10);
//设置数组的第5个元素
Array.set(array, 5, "hello");
//取出第5个元素
String str = (String)Array.get(array, 5);
System.out.println(str);
}
}
示例2:
package com.vvvv.reflect;
import java.lang.reflect.Array;
public class ArrayTester2{
public static void main(String[] args){
int[] dims = new int[] { 5, 10, 15 };
//创建一个长宽高分别为5、10、15的三维数组
Object array = Array.newInstance(Integer.TYPE, dims);
System.out.println(array instanceof int[][][]);
//获得array的第1维下标为3的component
Object arrayObj = Array.get(array, 3);
//获得arrayObj的第1维下标为5的component,并赋给arrayObj
arrayObj = Array.get(arrayObj, 5);
//设置arrayObj第10个元素的值
Array.setInt(arrayObj, 10, 37);
int[][][] arrayCast = (int[][][]) array;
System.out.println(arrayCast[3][5][10]);
// System.out.println(Integer.TYPE);
// System.out.println(Integer.class);
}
}
代理模式
1.静态代理
示例1:
抽象角色
package com.vvvv.proxy;
public abstract class Subject{
public abstract void request();
}
真实角色
package com.vvvv.proxy;
public class RealSubject extends Subject{
public void request(){
System.out.println("From real subject.");
}
}
代理角色
package com.vvvv.proxy;
public class ProxySubject extends Subject{
private RealSubject realSubject; //代理角色内部引用了真实角色
public void request(){
this.preRequest(); //在真实角色操作之前所附加的操作
if(null == realSubject){
realSubject = new RealSubject();
}
realSubject.request(); //真实角色所完成的事情
this.postRequest(); //在真实角色操作之后所附加的操作
}
private void preRequest(){
System.out.println("pre request");
}
private void postRequest(){
System.out.println("post request");
}
}
客户端
package com.vvvv.proxy;
public class Client{
public static void main(String[] args){
Subject subject = new ProxySubject();
subject.request();
}
}
2.动态代理
创建动态代理的步骤:
1.创建一个实现接口InvocationHandler的类,它必须实现invoke方法
2.创建被代理的类以及接口
3.通过Proxy的静态方法newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler h) 创建一个代理
4.通过代理调用方法
抽象角色与真实角色同上静态代理
动态代理句柄,可以动态的接收真实现角色、并调用真实角色的方法
package com.vvvv.dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
该代理类的内部属性是Object类型,实际使用的时候通过该类的构造方法传递进来一个对象
* 此外,该类还实现了invoke方法,该方法中的method.invoke其实就是调用被代理对象的将要
* 执行的方法,方法参数是sub,表示该方法从属于sub,通过动态代理类,我们可以在执行真实对象的方法前后
* 加入自己的一些额外方法。
*/
public class DynamicSubject implements InvocationHandler{
private Object sub;
public DynamicSubject(Object obj){
this.sub = obj;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable{
System.out.println("before calling: " + method);
method.invoke(sub, args);
System.out.println(args == null);
System.out.println("after calling: " + method);
return null;
}
}
客户端
package com.vvvv.dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Client{
public static void main(String[] args){
RealSubject realSubject = new RealSubject();
//动态代理句柄类拿到真实对象的引用,并构造一个对象
InvocationHandler handler = new DynamicSubject(realSubject);
Class<?> classType = handler.getClass();
//生成代理对象
Subject subject = (Subject) Proxy.newProxyInstance(
classType.getClassLoader(), //类加载器
realSubject.getClass().getInterfaces(), //真实对象实现的接口
handler);
subject.request();
System.out.println(subject.getClass());
}
}
自定义一个对Vector的动态代理句柄
package com.vvvv.dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Vector;
public class VectorProxy implements InvocationHandler{
//这里传入的真实对象将会是Vector的对象
private Object realObj;
public VectorProxy(Object obj){
this.realObj = obj;
}
//构造代理对象
public static Object factory(Object obj){
Class<?> classType = obj.getClass();
return Proxy.newProxyInstance(classType.getClassLoader(),
classType.getInterfaces(), new VectorProxy(obj));
}
//通过代理角色执行方法调用
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable{
System.out.println("before calling: " + method);
if(null != args){
//args是method的参数
for(Object obj : args){
System.out.println(obj);
}
}
//调用代理角色的目标方法
Object object = method.invoke(proxyObj, args);
System.out.println("after calling: " + method);
return object;
}
public static void main(String[] args){
List v = (List)factory(new Vector());
System.out.println(v.getClass().getName());
//通过代理对象v间接调用vector的方法
v.add("New");
v.add("York");
System.out.println(v);
v.remove(0);
System.out.println(v);
}
}
注解
说明
1.自定义注解:当注解中的属性名为 value 时,在对其赋值时可以不指定属性的名称而直接写上属性值即可;除了value 以外的其他值都需要使用 name=value这种赋值方式,即明确指定给谁赋值。
2.当我们使用@interface 关键字定义一个注解时,该注解隐含地继承了java.lang.annotation.Annotation 接口;如果我们定义了一个接口,并且让该接口继承自 Annotation,那么我们所定义的接口依然还是接口而不是注解;Annotation 本身是接口而不是注解。可以与Enum 类比。
自定义注解
示例1
AnnotationTest
package com.vvvv.annotation;
public @interface AnnotationTest{
String[] value1() default "hello";
EnumTest value2();
}
enum EnumTest{
Hello, World, Welcome;
}
AnnotationUsage
package com.vvvv.annotation;
@AnnotationTest(value2 = EnumTest.Welcome)
public class AnnotationUsage{
@AnnotationTest(value1 = {"world", "ABCD"}, value2 = EnumTest.World)
public void method(){
System.out.println("usage of annotation");
}
public static void main(String[] args){
AnnotationUsage usage = new AnnotationUsage();
usage.method();
}
}
@Retention及RetentionPolicy的使用
Retention可以指定注解的保留策略,包括Class,Runtime,Source三个范围域上。
示例2
MyAnnotation
package com.vvvv.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.CLASS)
public @interface MyAnnotation{
String hello() default "vvvv";
String world();
}
MyTest
package com.vvvv.annotation;
@MyAnnotation(hello = "beijing", world = "shanghai")
public class MyTest{
@MyAnnotation(hello = "tianjin", world = "shangdi")
@Deprecated
@SuppressWarnings("unchecked")
public void output(){
System.out.println("output something!");
}
}
利用反向射读取注解信息
示例3
AccessibleObject, Class, Constructor, Field, Method, Package都实现了AnnotatedElement接口. 定义Annotation时必须设定RetentionPolicy为RUNTIME,也就是可以在VM中读取Annotation信息。以下示例使用反射方式,读取出定义在类上的注解信息。
MyRefection
package com.vvvv.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class MyReflection{
public static void main(String[] args) throws Exception{
MyTest myTest = new MyTest();
Class<MyTest> c = MyTest.class;
Method method = c.getMethod("output", new Class[]{});
//判断这个注解上是否存在MyAnnotation的注解修饰
if(method.isAnnotationPresent(MyAnnotation.class)){
method.invoke(myTest, new Object[]{});
//获得MyAnnotation注解,并取出MyAnnotation注解的值
MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
String hello = myAnnotation.hello();
String world = myAnnotation.world();
System.out.println(hello + ", " + world);
}
//获得这个方法的所有注解
Annotation[] annotations = method.getAnnotations();
for(Annotation annotation : annotations){
//输出的内容由注解的RetentionPolicy决定
System.out.println(annotation.annotationType().getName());
}
}
@Target限定注解的使用时机
使用@Target定义注解的使用时机要指定java.lang.annotation.ElementType,是AccessibleObject,还是 Class, 或者Constructor, Field, Method, Package.
@Retention要搭配一个RetentionPolicy枚举类型, 同样@Target要搭配一个ElmentType 枚举类型。
示例4
MyTarget
package com.vvvv.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
public @interface MyTarget{
String value();
}
MyTargetTest
package com.vvvv.annotation;
public class MyTargetTest{
@MyTarget("hello")
public void doSomething(){
System.out.println("hello world");
}
}
1.使用java.lang.annotation.Documented修改注解,则可以将注解的信息加入到API文档中。
2.预设的父类别中的Annotation并不会继承到子类别中,但可以在定义Annotation型态时加上java.lang.annotation.Inherited型态的Annotation.