黑马程序员 ---- java基础加强(下)

时间:2021-11-13 00:40:48
 —————————— ASP.Net+Android+IOS开发.Net培训、期待与您交流!——————————


内省(IntroSpector) 对javaBean操作


如果在两个模块之间传递多个信息,可以将这些信息封装到一个javaBean中,这种javaBean的实例对象通常称为
值对象(Value Objeect);


如果属性的第二个字母为小写,那么第一个字母就是小写 
getCPU --  CPU
getTime--  time
gettime--  time


对javaBean的简单内省操作
PropertiesDescriptor属性描述类


getReadMethod();//get
getWriteMethod();//set


Extract 抽取


复杂的内省操作:
BeanInfo = IntroSpector.getBeanInfo();
在getPropertyDescriptors();
通过getName 在equals属性名



package day2;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


//简单的内省操作javaBean 和复杂的内省操作javaBean
public class EasyIntroSpector
{
public static void main(String[] args)throws Exception
{
Person person=new Person("其实我很在乎你",10);
String propertyName="name";
String setValue="累了醉了就想哭";

//设置
setProperty(person, propertyName, setValue);


//获取
getProperty(person, propertyName);




}

private static void setProperty(Person person, String propertyName, String setValue)
throws IntrospectionException, IllegalAccessException, InvocationTargetException
{

//简单的内省操作
/*
PropertyDescriptor pDescriptor=new PropertyDescriptor(propertyName, person.getClass());
Method method=pDescriptor.getWriteMethod();
method.invoke(person, setValue);
*/

//复杂的内省操作
BeanInfo beanInfo= Introspector.getBeanInfo(person.getClass());
PropertyDescriptor[] pDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : pDescriptors)
{
if(propertyDescriptor.getName().equals(propertyName))
{
Method method=propertyDescriptor.getWriteMethod();
method.invoke(person, setValue);
}
}
}

private static void getProperty(Person person, String propertyName)
throws IntrospectionException, IllegalAccessException, InvocationTargetException
{
//简单的内省操作

/*PropertyDescriptor pdDescriptor=new PropertyDescriptor(propertyName, person.getClass());

Method method=pdDescriptor.getReadMethod();
System.out.println(method.invoke(person));*/

//复杂的内省操作

BeanInfo beanInfo=Introspector.getBeanInfo(person.getClass());

PropertyDescriptor[] propertyDescriptors=beanInfo.getPropertyDescriptors();

for (PropertyDescriptor propertyDescriptor : propertyDescriptors)
{
if(propertyDescriptor.getName().equals(propertyName))
{
Method method=propertyDescriptor.getReadMethod();
System.out.println(method.invoke(person));
}
}
}
}



使用BeanUtils工具类操作Bean
getProperty();
setProperty();


例如Date  符合属性  属性可以级联




PropertiesUtils操作Bean


BeanUtils与PropertiesUtils区别
1.BeanUtils可以使用字符串内部会自动转换,而PropertiesUtils只能使用本身的属性类型


package day2;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;

//使用BeanUtils工具包操作 javaBean
public class BeanUtilsTest
{
public static void main(String[] args)throws Exception
{

//BeanUtils与PropertyUtils的区别
//前者可以传入字符串,内部会自动转换, 后者只能传自身属性的类型,因为内部不会有转换


Person person=new Person("关不上的窗",15);
String propertyName="name";
String setValue="我的故乡黑龙江";

BeanUtils.setProperty(person, propertyName, setValue);

String name=BeanUtils.getProperty(person, propertyName);

System.out.println(name);

String proString="age";

//不能传入字符串 内部不会自动转换 自己传自身的类型
//PropertyUtils.setProperty(person, proString, "15");
PropertyUtils.setProperty(person, proString, 60);

int age = (int)PropertyUtils.getProperty(person,proString);

System.out.println(age);


//Date级联 属性

System.out.println(BeanUtils.getProperty(person, "date.time"));

}
}



几个基本注解(Annotation)
1.@SuppressWarnings(); //传入的是数组,当只有一个值可以直接传入 {"unused","unchecked","deprecation","rawtypes"}
2.@Deprecated  //过时的
@Override //重写   


一个注解就是一个类


注解相当与一种标记,加了注解就等于打上了某种标记,没加就等于没有这种标记,以后javac编译器,开发工具和其他程序
就可以用反射来了解你的类及各种元素上有无何何种标记,告诉你有什么标记,就去干相应的事


标记可以加在包中,构造方法,普通方法,类,局部变量,成员变量上..


package day2;
//注解的入门
public class AnnotationTest
{
@SuppressWarnings("deprecation")//压缩警告,过时方法不警告
public static void main(String[] args)
{

show();
System.runFinalizersOnExit(false);


}
@Deprecated //标志为已过时方法
public static void show()
{
System.out.println("show方法");
}

@Override //加上注解如果复写方法不对 会编译错误
public String toString()
{
return AnnotationTest.class.getName();
}
}



注解类的应用结构


1.注解类 @interface
2.应用了注解的类
3.对应用了注解的类进行反射操作


isAnnotationPresent(注解类.class); 




@Retent(RetentionPolicy.RUNTIME) 保留运行期间
RetentionPolicy.SOURCE  保留在源文件上
RetentionPolicy.CLASS   保留在class字节码文件上


@Target({ElementType.METHOD})  注解可以存放位置例如方法METHOD,类TYPE
ElementType.METHOD
ElementType.FIELD
ElementType.LOCAL_VARIABLE
ElementType.TYPE
ElementType.PARAMTER
ElementType.CONSTRUCTOR
ElementType.PACKAGE
ElementType.ANNOTATION_TYPE


为注解类添加基本属性
String 
int[]
只有一个设置值时,可以直接传入


可以设置默认值 加上default关键字即可


为注解添加高级属性,  枚举,注解类,Class等


package day2;
//注解的入门
public class AnnotationTest
{
@SuppressWarnings("deprecation")//压缩警告,过时方法不警告
public static void main(String[] args)
{

show();
System.runFinalizersOnExit(false);


}
@Deprecated //标志为已过时方法
public static void show()
{
System.out.println("show方法");
}

@Override //加上注解如果复写方法不对 会编译错误
public String toString()
{
return AnnotationTest.class.getName();
}
}


package day2;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Itcast
{
int value(); //当方法名为Value 只有一个参数可以 直接注解类(值)
}



package day2;

import java.lang.reflect.Method;
import java.nio.file.AccessMode;
import java.util.Arrays;

import day1.EnumTest3.Lamp;


//注解的高级应用
@AnnotationClass(getName = "类上")
public class AnnatationTest1
{
@SuppressWarnings("rawtypes")
@AnnotationClass(getName="方法上")
public static void main(String[] args)throws Exception
{
if(AnnatationTest1.class.isAnnotationPresent(AnnotationClass.class))
{
//注解类
AnnotationClass aClass=AnnatationTest1.class.getAnnotation(AnnotationClass.class);
System.out.println(Arrays.toString(aClass.getArr()));

System.out.println(aClass.getClass().getName());
System.out.println(aClass.getClass().getSuperclass().getName());


Itcast itcast=aClass.getItcast();
System.out.println(itcast.getClass().getName());
System.out.println("value值是:"+itcast.value());

Lamp lamp=aClass.getLamp();
System.out.println(lamp);
System.out.println(lamp.nextLamp());

Class clazz=aClass.getClassName();
System.out.println(clazz.getName());

}

Method method = AnnatationTest1.class.getMethod("main", String[].class);

if(method.isAnnotationPresent(AnnotationClass.class))
{
AnnotationClass aClass=AnnatationTest1.class.getAnnotation(AnnotationClass.class);
System.out.println(aClass.getName());
}

}
}



泛型 
好处: 安全,避免了强制转换的麻烦


一个ArrayList<Integer>用反射来添加String元素

package day2;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
//反射 一个ArrayList<Integer>参数化类型 可以添加String实际类型参数
public class ReflectGeneric
{
public static void main(String[] args)throws Exception
{
List<Integer> list=new ArrayList<Integer>();
list.add(1);
System.out.println(list);

//反射 获取add方法
Method addMethod=list.getClass().getMethod("add", Object.class);

addMethod.invoke(list, new String("星星点灯"));

System.out.println(list);
}
}




ArrayList<E> 代表泛型类型 
ArrayList<E> E代表类型变量,类型参数
ArrayList<Integer> 称为参数化类型
ArrayList<Integer> Integer称为类型参数,或类型参数实例
ArrayList<Integer> 念ArrayList typeof Integer
ArrayList 代表原始类型


参数化类型可以引用一个原始类型
Collection col=new ArrayList<Integer>();
原始类型可以引用一个参数化类型
Collection<Integer> col=new ArrayList();


参数化类型不存在继承关系
<String>  <object>   //不行
<Object>   <String>  //不行


在创建数组实例时,数组元素不能使用参数化类型
Vector<Integer>[] vectors=new Vector<Integer>[10]; //这是不允许的


思考题:
Vector v=new Vector<Integer>();//参数类类型引用给原始类型 允许的
Vector<Object> v1= v;  //原始类型类参数化类型 可以的 


泛型通配符扩展应用


? 代表任意类型,不确定的类型


只能作为传参引用时,调用与添加有关的参数时不行,只能调用与参数类型无关的方法


上限符:
<? extends Number>   只能接收Number或者该子类


下限符:
<? super Integer>   只能接收Integer以及他的父类


限定符总是包括自己


package day2;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

//泛型通配符扩展应用
public class GenericTest
{
public static void main(String[] args)
{
//print(new int[]{1,2,3}); //编译错误, 基本类型不能当作为实际参数
print(new String[]{"a","b"}); //可以, 引用类型数组可以

ArrayList<Integer> aList=new ArrayList<Integer>();
aList.add(10);
aList.add(1);

//show(aList);
show1(aList);

//上限符
ArrayList<? extends Number> al1=new ArrayList<Integer>();


//下限符
ArrayList<? super Integer> al3=new ArrayList<Integer>();
//String 不是Integer的父类
//ArrayList<? super Integer> al2=new ArrayList<String>();


}
public static <T> void print(T [] arr)
{
System.out.println(arr.length);
}
// ?代表不确定的类型 任意类型
public static void show(Collection<?> c)
{
//当?作为引用是时, 不能调用与添加有关的方法,只能使用与参数类型无关的方法

System.out.println(c.toString());
//c.add(1); 不能使用
c.clear();
}
//T 代表确定的类型
public static <T> void show1(Collection<T> c)
{
//当?作为引用是时, 不能调用与添加有关的方法,只能使用与参数类型无关的方法

System.out.println(c.toString());
//c.add(1); 不能使用
Iterator<T> it=c.iterator();
while (it.hasNext())
{
T t=it.next();
System.out.println(t);

}

}
}



泛型的综合案例,  HashMap添加元素


package day1;

import java.util.HashMap;
import java.util.Map;


//泛型实例 Map
public class EnhanceFor
{
public static void main(String[] args)
{
Map<String, String> map = new HashMap<String, String>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");

for (Map.Entry<String, String> mEntry : map.entrySet())
{
System.out.println(mEntry.getKey()+"---"+mEntry.getValue());
}



自定义泛型方法
// x y 可以传入任意类型, 最大的交集就是Object 
private static <T> T add (T x , T y)
{
//return x+y; 这是不允许的,因为类型的不确定是否能运算
return x;
}


java泛型完全是在编译器中实现的


T不能是基本类型,只能是引用类型,才能作为实际参数


<V extends Serializable&Cloneable> 必须实现这两接口的类型


普通类,构造方法,静态方法,都可以使用泛型


数组实例不能使用参数化类型


泛型参数可以有多个,例如Map<K,V>


泛型的类型推断还有传递性


泛型类
 

 静态不能使用泛型类


package day2;
//泛型类
public class GenericClass<T>
{
@SuppressWarnings("unused")
private T t;
/*
//静态方法不能使用 类泛型
public static void show(T t)
{

}
*/
public static <T> void method(T t)
{

}

public void show(T t)
{
System.out.println(t);
}

}




 通过反射获取泛型的实际参数类型
 
 getGenericParamterTypes();
 getParameterTypes();
 ParameterizedType参数化类型类
 
 getRawType();
 getActualTypeArguments();

 

package day2;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;

//反射获取参数泛型类型
public class GenericTest1
{
public static void main(String[] args)throws Exception
{
show(new String("尼玛"));
show(new Integer(1));

Method method=GenericTest1.class.getMethod("print", Collection.class);

Type[] types = method.getGenericParameterTypes();

ParameterizedType pType=(ParameterizedType)types[0];

System.out.println(pType.getRawType());
//System.out.println(pType.getActualTypeArguments()[0]);
Type[] types2=pType.getActualTypeArguments();
System.out.println(types2[0]);


}
//接收任意类型并打印
public static <T> void show(T t)
{
System.out.println(t);
}
public static void print(Collection<String> collection)
{

}
}


 类加载器   加载类的工具


 系统默认的三个主要加载器
 1.BootStrap   查找rt.jar
 2.ExtClassLoader 查找ext/下的jar包
 3.AppClassLoader 查找classpath路径
 
 类加载器也是java类,BootStrap不是,是c写的二进制文件
 
类.getClassLoader();获取当前类的类加载器
getParent();  //获取父类


因为BootStrap不是java类,所以返回null


java中所有的类加载都是采用父子关系的树状结构图进行组织


ClassLoader类

package day3;
//遍历 类加载器
public class ClassLoaderbase
{
public static void main(String[] args)
{
ClassLoader loader=ClassLoaderbase.class.getClassLoader();
System.out.println(loader);
while(loader!=null)
{
loader=loader.getParent();
System.out.println(loader);
}

//最*的父类BootStrap因为不是java类 所以返回null
}

}




类加载器的委托机制
首先会找对*的父类,如果没有就一级一级的往下查找,如果到了触发者这里还没有就抛ClassNotFoundException


自定义加密Class文件
自定义解密Class文件

package day3;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import com.sun.org.apache.bcel.internal.util.ByteSequence;

//加解密 自动加载器类
@SuppressWarnings("unused")
public class MyClassLoader extends ClassLoader
{

private String classDir;
public MyClassLoader(String classDir)
{
this.classDir=classDir;
}
public static void main(String[] args)throws Exception
{
String yuan=args[0];
String filename=yuan.substring(yuan.lastIndexOf(File.separator)+1);
String mudi=args[1]+File.separator+filename;

FileInputStream fis=new FileInputStream(yuan);
FileOutputStream fos=new FileOutputStream(mudi);
EncryptionAndDecryption(fis, fos);


}
public static void EncryptionAndDecryption(InputStream inStream,OutputStream outStream)
{
try
{
int b=0;
while((b=inStream.read())!=-1)
{
outStream.write(b ^ 0xff);
}
} catch (Exception e)
{
System.out.println("加解密文件失败");
}finally
{
try
{
if(inStream != null)
inStream.close();
} catch (Exception e2)
{
System.out.println("关流失败");
}
try
{
if(outStream != null)
outStream.close();
} catch (Exception e2)
{
System.out.println("关流失败");
}
}
}
//只需要复写findClass方法 就可以自动以类加载器了
@SuppressWarnings("deprecation")
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException
{
// TODO Auto-generated method stub
String filePath=classDir+File.separator+name+".class";
try
{
FileInputStream inStream=new FileInputStream(filePath);

ByteArrayOutputStream baos=new ByteArrayOutputStream();

EncryptionAndDecryption(inStream, baos);

inStream.close();

byte[]buf =baos.toByteArray();

return defineClass(buf, 0, buf.length);

} catch (Exception e)
{
// TODO: handle exception
}

return null;
}
}


package day3;


public class ClassLoaderTest
{
public static void main(String[] args)throws Exception
{
//使用已经加密的class文件new 运行出错
//System.out.println(new Test());
new MyClassLoader("E:\\android\\projects\\javaenhance1\\bin\\day3").loadClass("Test").newInstance();
}
}


loadClass();加载类
  我们只需要复写findClass路径添加为自己的路径即可
  
  defineClass(); 接收字节数组返回class
  
 有包的类不能调用无包的类
 
一个类加载器的高级问题分析web




代理的概念与作用
Proxy代理


AOP (Aspect Oriented Program) 面向方面的编程


安全,事物,日志等功能要贯穿好多个模块中,他们就是交叉业务


AOP中,将交叉业务模块化,可以将切面代码异移动到原始方法的周围


动态代理技术


jvm自动生成类, 动态生成类,即动态代理类


package day3;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;

//动态代理类 演示
public class ProxyTest
{
public static void main(String[] args)
{
Class clazz = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);

Constructor[] constructors=clazz.getConstructors();
for (Constructor constructor : constructors)
{
StringBuilder sbBuilder=new StringBuilder(constructor.getName());

Class[] classes=constructor.getParameterTypes();
sbBuilder.append('(');
for (Class class1 : classes)
{
sbBuilder.append(class1.getName());
}
if(classes!= null && classes.length!=0)
sbBuilder.deleteCharAt(sbBuilder.length()-1);
sbBuilder.append(')');

System.out.println(sbBuilder.toString());
}

Method[] methods=clazz.getMethods();
for (Method method : methods)
{
StringBuilder sbBuilder=new StringBuilder(method.getName());
Class[]classes=method.getParameterTypes();
sbBuilder.append('(');
for (Class classs : classes)
{
sbBuilder.append(classs.getCanonicalName());
}
sbBuilder.append(')');
System.out.println(sbBuilder.toString());
}
}
}



动态代理生成必须实现一个或多个接口  


CGLIB可以生成没有接口的子类,代理类


Proxy.getProxyClass(); 
Proxy.newProxyInstance();

package day3;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;


//代理类实例化
public class ProxyTest1
{
public static void main(String[] args)throws Exception
{

//麻烦的实例化代理对象做法


Class clazz = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);

Constructor constructor=clazz.getConstructor(InvocationHandler.class);

Collection collection=(Collection)constructor.newInstance(new InvocationHandler()
{
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
// TODO Auto-generated method stub
return null;
}
});
//返回为空
System.out.println(collection);
System.out.println(collection.toString());
//collection.add("add");//不能添加
System.out.println(collection.size()); //null 不能调用需要实例化对象的方法


//简单的一部到位做法

Collection collection1=(Collection)Proxy.newProxyInstance(
Collection.class.getClassLoader(),
new Class[]{Collection.class},
new InvocationHandler()
{

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
// TODO Auto-generated method stub
return null;
}
});
//返回为空
System.out.println(collection1);
System.out.println(collection1.toString());
//collection.add("add");//不能添加
System.out.println(collection1.size()); //null 不能调用需要实例化对象的
}
}



要有一个目标,一个建议


Client程序用Proxy的方法时,涉及三要素:代理对象 , 代理对象的方法, 方法参数


把目标返回结果返回到代理上


可以将代码封装对象,放在原方法的四个位置:
1.前
2.后
3.中间
4.catch处理代码块中


建议Advice接口  
目标就是要生成代理类的类

package day3;

import java.lang.reflect.Method;

public interface Advice
{
void beforMethod(Method method);
void affterMethod(Method method);
}


package day3;

import java.lang.reflect.Method;

public class MyAdvice implements Advice
{
private long startTime;
private long endTime;
@Override
public void beforMethod(Method method)
{
startTime=System.currentTimeMillis();
System.out.println("事物,安全,日志 代码前 ");

System.out.println("方法名"+method.getName());
}

@Override
public void affterMethod(Method method)
{

endTime=System.currentTimeMillis();
System.out.println("执行所花费时间:"+(endTime-startTime));
System.out.println("事物,安全,日志 代码后 ");
}

}



package day3;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
//代理类 封装成方法 对象
public class ProxyTest3
{
public static void main(String[] args)
{
final ArrayList target=new ArrayList();
final Advice advice=new MyAdvice();

Collection collection=(Collection)getProxy(target, advice);
collection.add("dd");
}

private static Object getProxy(final ArrayList target, final Advice advice)
{
Object object = Proxy.newProxyInstance(
target.getClass().getClassLoader()
, target.getClass().getInterfaces()
, new InvocationHandler()
{
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
advice.beforMethod(method);
Object returnVal=method.invoke(target, args);
advice.affterMethod(method);
return returnVal;
}
});
return object;
}
}



实现类似Spring中的Aop框架
BeanFactory
getBean();
ProxyFactoryBean

getProxy();


package day3;

import java.io.InputStream;

public class AOPTest
{
public static void main(String[] args)
{
InputStream inStream=AOPTest.class.getResourceAsStream("lib/aop.properties");
Object object = new BeanFactory(inStream).getBean("className");
System.out.println(object);
}
}

package day3;

import java.io.InputStream;
import java.util.Properties;


public class BeanFactory
{
private Properties properties=new Properties();
public BeanFactory(InputStream inStream)
{
try
{
properties.load(inStream);
} catch (Exception e)
{
// TODO: handle exception
}
}
@SuppressWarnings("rawtypes")
public Object getBean(String name)
{
Object bean=null;
String className=properties.getProperty(name);
try
{
Class clazz=Class.forName(className);
bean=clazz.newInstance();
} catch (Exception e)
{
// TODO: handle exception
}
if(bean instanceof ProxyFactoryBean)
{
Object proxy=null;
ProxyFactoryBean pBean=(ProxyFactoryBean)bean;
try
{
Advice advice=(Advice)Class.forName(properties.getProperty(name+".advice")).newInstance();
Object target=Class.forName(properties.getProperty(name+".target")).newInstance();
pBean.setAdvice(advice);;
pBean.setTarget(target);

proxy = pBean.getProxy();

return proxy;
} catch (Exception e)
{
System.out.println("获取异常");
}
}
return bean;
}
}

package day3;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyFactoryBean
{
private Object target;
private Advice advice;

public Object getTarget()
{
return this.target;
}

public void setTarget(Object target)
{
this.target = target;
}

public Advice getAdvice()
{
return this.advice;
}

public void setAdvice(Advice advice)
{
this.advice = advice;
}

public Object getProxy()
{
final Object target=getTarget();
final Advice advice=getAdvice();
Object object = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler()
{

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
advice.beforMethod(method);
Object returnValue=method.invoke(target, args);
advice.affterMethod(method);
return returnValue;
}
});
return object;
}
}


 —————————— ASP.Net+Android+IOS开发.Net培训、期待与您交流!——————————