---------------------- android培训、java培训、期待与您交流! ----------------------
马上去黑马学习了 又回过头来把张老师的视频过一遍心里有点低 嘿嘿 在
黑马
学习很有压力的
自动装箱和自动拆箱:
Integer obj=3;//自动装箱的操作把一个基本数据类型给一
个
对象
System.out.println(obj+12);//自动拆箱的操作
引出了一个自动装箱的小知识细节
Integer i1=13;
Integer i2=13;
把一个基本数据类型的整数装箱成为一个Integer对象的时
候
如果这个数字在一个字节之内(-128~127之间)一旦包装对
象后
会缓存在池中 当我再次调用的时候回去从池中去拿 这样
做
是为了节省内存空间为了 当多个地方需要同一个对象的时
候
不用去每次去实例化对象而是去指向同一个对象 不同的
是
用的地方不同这样就就是享元模式的原理
享元模式:在一个txt文件中有26个字母拼成的无数的单词 每个单词中的
每一
个字母都是一个对象都是引用第一个对象一共有36个小对象不同的只是
引用
对象的位置个名字~~哈哈 理解很透彻哦~~
Integer i3=Integer.valueOf(3);
Integer i4=Integer.valueOf(3);
把两个基本数据类型的整形封装成对象在一个字节之内
也是
用的是同一个对象 在池内存中只有一个3 但是有两个对
象
同时指向它 所以System.out.println(i3==i4);的答案是true
枚举:JDK1.5以后推出的新特性
什么是枚举 为什么要用枚举??
用一个抽象类来模仿一个枚举的功能:
public abstract class WeekDay {
public WeekDay() {
}
public static final WeekDay SUN = new WeekDay() {
@Override
public WeekDay nextDay() {
// TODO Auto-generated method stub
return WON;
}
};
public static final WeekDay WON = new WeekDay() {
@Override
public WeekDay nextDay() {
return SUN;
}
};
// public WeekDay nextDay(){
// if(this==SUN){
// return WON;
// }else{
// return SUN;
// }
// }
public abstract WeekDay nextDay();
public String toString() {
return this == SUN ? "SUN" : "MON";
}
}
定义抽象方法将大量的ifelse语句转移成了一个个独立的类
public enum Lamp{
RED(30) {
@Override
public Lamp nextLamp() {
// TODO Auto-generated method stub
return GREEN;
}
},GREEN(45) {
@Override
public Lamp nextLamp() {
// TODO Auto-generated method stub
return YELLOW;
}
},YELLOW(10) {
@Override
public Lamp nextLamp() {
// TODO Auto-generated method stub
return RED;
}
};
private Lamp(){}
private int time;
private Lamp(int time){
this.time=time;
}
public abstract Lamp nextLamp();
}
枚举中每一个元素都是一个对象 在枚举中定义一个抽象方法那
么自
己的子类对象都必须去实现这样就是每个对象都有自己单独的方法
反射:是JDK1.2的特性必须了解关键字Class
得到一个类的字节码文件有三种方式
1.Person.class-->同一个存在的类
2.new Personb.getClass()//通过实例对象获取字节码对象
3.Class.ForName("className")//推荐使用 推展性高 再编写
代码
的时候并不知道要加载的类是哪一个类可 用
通过
一字符串对象来传递
9个预定义对象8中基本数据类型还有void.class
每一个类的字节码内存中独一份
反射就是把Java中的各种成分映射成相应的Java类 一个Java类中
用一
个Class对象表示来表示一个类中的组成部分:成员变量、成员方法
构
造方法、包等信息也用一个个的Java类来表示
我所理解的反射:我有一台电脑 我想得到笔记本中的零件 比如显卡 处理
器
内存条 主板。。。电脑自己知道这些零件怎么装的怎么用的 怎么拆的 我
不
知道 我就得先去得到笔记本 之后 我有我自己专门的得到笔记本的方法
可
以成为拆显卡的类 拆内存的类 然后按照 我的方式一一击破 得到各个元
件
通过构造函数获取一个类的构造函数通过构造函数的参数
的
类型和个数来判定去实例哪个构造函数
Constructor
orconstruct=String.class.getConstructor(StringBuffer.class)
;//
获取一个参数是StringBuffer类型的构造函数
String str=(String)orconstruct.newInstance(new
StringBuffer("abc"));//通过传递一个StringBuffer类型的实际
参
数实例化一个String类型的对象
System.out.println(str.charAt(2));//测试得到的String对象
反射会导致程序性能严重下降****************************************
获取一个类中的地段 公有字和私有字段的是由区别的
ReflectPoint rp=new ReflectPoint(3, 5);
Field fieldY=rp.getClass().getField("y");//获取一个
ReflectPoint类的字节码对象中的公有字段y
Object obj=fieldY.get(rp);//在rp这个对象身上得到
System.out.println(obj);
Field fieldX=rp.getClass().getDeclaredField("x");//在
ReflectPoin字节码对象中得到私有字段x
fieldX.setAccessible(true);//设置私字段的检查权限-->暴
力破
解
Object objx=fieldX.get(rp);//在rp身上得到值
System.out.println(objx);
案例:得到一个类中所有的String类型的字段 将字段中的每个字
符'b'改成'a'
private static void changeValue(Object obj) throws
Exception,
Exception {
Field[] fields=obj.getClass().getFields();
for (Field field : fields) {
if(field.getType()==String.class){//注意:这里为什
么
要用==因为字节码在内存中独一份没有必要去用
equals方法
String oldValue=(String)field.get(obj);
String newValue=oldValue.replace('b', 'a');
field.set(obj, newValue);
}
}
}
用反射的方式执行某个类中的main方法
String className=args[0];
Method
mainMethod=Class.forName(className).getMethod("main",
String[].class);
//mainMethod.invoke(null, new Object[]{new
String[]{"111","222"}});//因为main在接收参数的时候默认
的是
接受一个Object数组会把它打开String[]{"111","222"}打开
之
后是两个参数所以不能和main方法匹配
mainMethod.invoke("main", (Object)new
String[]{"111","222","333"});//将String类型的数组转换强
制
转换成Object类型的在编译的时候会将数组作为Object数组
进
行参数传递
数组个Object的关系和反射
每一个数组都属于同一个Class,具有相同的元素类型以及具有相
同
的维度
int[] a1=new int[2];
int[] a2=new int[3];
int[][] a3=new int[3][4];
String[] s1=new String[5];
System.out.println(a1.getClass());
System.out.println(a3.getClass());
// System.out.println(a1.getClass()==a3.getClass());//编译器
会
报错一个因为一个一维数组和一个二维数组没课有可比性两种完全不同类
型(
一个装的是基本数据类型,另一个装的是Object类型,所以会报错)
System.out.println(a1.getClass()==a2.getClass());
// System.out.println(s1.getClass()==a3.getClass());
Object o1=a1;//一维数组本省就是Object类型
Object o2=a3;//一样数组中的数组也是Object类型
// Object[] oo1=a1;//因为int类型的数组中全是基本数据类
型
Object[] oo2=a3;//数组中的数组也是一个Object外面的数
组
就是一个Object数组
Object[] oo3=s1;//String数组中每一个元素都是Object类
型的
模拟一个框架反射一个集合(用类加载器):
//InputStream fis=new FileInputStream("config.properties");
//InputStream
fis=ReflectTest.class.getClassLoader().getResourceAsStream(
"co
m/cn/hah/enumDemo/config.properties");
InputStream
fis=ReflectTest.class.getResourceAsStream("config.propertie
s")
;
Properties prop=new Properties();
prop.load(fis);
fis.close();
String className=prop.getProperty("className");
Collection coll=(Collection)
Class.forName(className).newInstance();
ReflectPoint p1=new ReflectPoint(3, 5);
ReflectPoint p2=new ReflectPoint(0, 1);
ReflectPoint p3=new ReflectPoint(3, 5);
Collection collection=new HashSet();
coll.add(p1);
coll.add(p2);
coll.add(p3);
coll.add(p1);
/*
* 这里会引起一个内存泄漏
*/
p1.y=7;
coll.remove(p1);//当改变了参与hashCode运算的属性的时候
会
改变对象的存储区域找不到那个要删除的对象引起内存泄
露
System.out.println(coll.size());
/*-->在没有重写HashCode和Equals方法之前
collection.add(p3);//这里的p3虽然和p1是同一个对象但是
所处
的区域不同依然可以放入集合中
collection.add(p1);//这里就是和p1同一个对象的没有被放
入
集合当中
*/
/*
*HashCode的作用:再往Hash集合中存放对象的时候会将
Hash分
为多个区域每存入一个对象
*都会计算它的的哈希码对一个整数取模 根据取模的数
值其
匹配一个区域 以后在放入的对象
*都会起执行此操作如果哈希码就不在存入否则存入这样
的
操作不用去判断每一个元素加快了效率去重复效率非
常快
*/
由内省引出JavaBean
JavaBean:是一个特殊的Java类 方法的名称符合某种约定的规则
如果要在两个模块当中传递多个信息可以将这些信息封装到这个
JavaBean中这种Javabean的实例对象通常被称之为值对象(Value
Object)
利用Java中提供的类来实现:
public static void main(String[] args) throws Exception {
ReflectPoint rp=new ReflectPoint(3, 5);
String propertyName="x";
Object retVal = getProperty(rp, propertyName);
System.out.println(retVal);
Object value=1000;
setProperty(rp, propertyName, value);
System.out.println(rp.getX());
}
private static void setProperty(ReflectPoint rp, String
propertyName,
Object value) throws IntrospectionException,
IllegalAccessException, InvocationTargetException {
PropertyDescriptor dp1=new PropertyDescriptor(propertyName,
rp.getClass());
Method methodSetX=dp1.getWriteMethod();
methodSetX.invoke(rp, value);
}
private static Object getProperty(ReflectPoint rp, String
propertyName)
throws IntrospectionException,
IllegalAccessException,
InvocationTargetException {
PropertyDescriptor pd=new PropertyDescriptor(propertyName,
rp.getClass());
Method methodX=pd.getReadMethod();
Object retVal= methodX.invoke(rp);
return retVal;
}
通过BeanInfo类对象 设置JavaBean的属性:
public static void main(String[] args) throws Exception {
ReflectPoint rp=new ReflectPoint(3, 5);
String propertyName="x";
Object value = getProperty(rp, propertyName);
System.out.println(value);
ReflectPoint rp1=new ReflectPoint(6, 9);
String PropertyName="x";
PropertyDescriptor ps1=new PropertyDescriptor(PropertyName,
rp1.getClass());
Method methodSetX=ps1.getReadMethod();
methodSetX.invoke(rp1, 1555);
System.out.println(rp1.getX());
}
private static Object getProperty(ReflectPoint rp, String
propertyName)
throws IntrospectionException,
IllegalAccessException,
InvocationTargetException {
// PropertyDescriptor pd=new PropertyDescriptor(propertyName,
rp.getClass());
// Method methodGetX=pd.getReadMethod();
// Object value=methodGetX.invoke(rp);
Object value=null;
BeanInfo beanInfo=Introspector.getBeanInfo(rp.getClass());
PropertyDescriptor[]descriptors=
beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : descriptors) {
if(propertyDescriptor.getName().equals(propertyName
)){
System.out.println("123");
Method
methodGetX=propertyDescriptor.getReadMethod
();
value=methodGetX.invoke(rp);
}
}
return value;
}
JDK1.5之后的新特性:枚举和注解
注解是向编译器传达某种信息
总结:注解相当于一种标记加了注解就相当于打上了某种标记 没
加则
等于没有某种标记,以后Javac编译器开发工具和其他程序可以用
反射
来了解你的类以及各种元素上有无任何标记,有什么标记就去干
相应
的事,标记可以加载包、类、字段、方法、方法的参数、以及局部变
量上
注解的生命周期有三个阶段:源文件-->class文件-->内存中字节码这三
个
阶段都有可能去掉源文件中的注解默认的值是class阶段
泛型:是提供给Javac编译器的可以限定集合中的输入类型让编译器挡住源
程序
的非法输入编译器编译带类型说明的集合时会去掉类型的信息,使程序的效
率
不受影响 对于参数化的泛型类型 getClass()方法的返回值和原始类型完
全一
样由于编译器的生成的字节码会自动的去掉泛型的类型信息 只要能跳过编
译
器就可以往某个泛型集合中加入其他类型的信息例如 用反射得到一个
Integer类型泛型类集合在里面添加String类型的数据也是可以的
(JDK1.5以后的自动装箱功能)
说白了 泛型是个编译器看的
通过反射获得泛型的实际类型参数:
当我们拿到一个任意泛型类型的对象时没有办法拿到它的泛型因
为编
译器在编译源文件的时候会去掉类型 所以泛型类型的对象可以以
参
数的角色通过一个方法得到参数 利用发射来解析参数的泛型类
型
====================================================================
类加载器:加载类的工具 我们在Java程序里面用到一个类,Java虚拟机会把
这
个类加载到硬盘中来 在对他进行处理这些工作都是类加载器去工作
Java虚拟机中可以加载多个类加载器,系统默认三个主要的类加载
器每
个类负责加载特定位置的类
BootStrap、ExtClassLoader、AppClassLoader
当Java虚拟机要加载一个类时 到底排排出哪个类加载器去加载
首先当前线程的类Thread类加载线程中的第一个类
如果类A中引用了类BJava虚拟机将会使用加载类A 的加载器
来
加载类B
还可以直接调用ClassLoader.loadclass()方法来制定某个类
加载
器去加载某个文件
自定义类加载器的写法
1、必须继承ClassLoader(抽象奥类)
-->内部自动实现loadClass(String name)是在父类中
找如果找不到会调用自己重写的findClass(String
name)方法,得到了class文件的数据转换成字节码
-->definClass()
代理:代理类的各个方法通常除了要调用目标的相应的方法和返回目标但
会结果外还可以在代理方法中的如下四个位置加上系统功能的代码“
1、调用目标方法之前。
2、调用目标方法之后。
3、在调用目标方法前后。
4、在处理目标方法的异常的catch块中