推荐下载Android框架基础知识梳理Word格式.docx
- 文档编号:17159916
- 上传时间:2022-11-28
- 格式:DOCX
- 页数:19
- 大小:23.30KB
推荐下载Android框架基础知识梳理Word格式.docx
《推荐下载Android框架基础知识梳理Word格式.docx》由会员分享,可在线阅读,更多相关《推荐下载Android框架基础知识梳理Word格式.docx(19页珍藏版)》请在冰豆网上搜索。
User、Girl、Beauty等等因此,每个APP会
创建一个自己的ClassLoader实例,该ClassLoader用于加载dex
privatevoidgetClassLoaders(){ClassLoaderclassLoader=getClassLoader();
while
(null!
=classLoader){System.out.println(“----classLoader=“+classLoader);
classLoader
=classLoader.getParent();
}}
此处一共展示了三个ClassLoader
第一个ClassLoader,如下:
dalvik.system.PathClassLoader[DexPathList[[zip_file”/data/app/com.lizi.classloaderdemo-
1/base.apk”],nativeLibraryDirectories=[/data/app/com.lizi.classloaderdemo-1/lib/x86,
/vendor/lib,/system/lib]]]
该PathClassLoader在应用启动时创建,用于加载/data/app/cc.testreflection-
2/base.apk中的类
ClassLoader是一个抽象类,它有三个常用的子类:
PathClassLoader、
URLClassLoader、DexClassLoader
PathClassLoader它只能加载已经安装的apk中的资源,比如dex文件
URLClassLoader它只能用于加载jar文件中的资源。
但是dalvik不能直接识别jar,
因此这个加载器极少使用。
DexClassLoader它用于从.jar和.apk类型的文件内部加
载classes.dex。
该类加载器常用来完成动态加载apk的需求第二个ClassLoader,我
不是很清楚,嘿嘿,欢迎指点。
第三个ClassLoader,如下:
java.lang.BootClassLoader@112e4ef该BootClassLoader在系统启动的时候创建,用
于加载系统层级的类
看看解释的这两个类加载器的应用
privatevoidtestClassLoader(){try{Classclazz=
Class.forName(“cc.testreflection.Girl”);
ClassLoaderclassLoader=
clazz.getClassLoader();
System.out.println(“----classLoader=“+classLoader);
classLoader=mContext.getClass().getClassLoader();
InputStreaminputStream=
classLoader.getResourceAsStream(“assets/ic_launcher.png”);
System.out.println(“----
classLoader=“+classLoader);
clazz=Class.forName(“java.lang.String”);
classLoader=
}catch
(Exceptione){}}
我们自己的类com.lizi.classloaderdemo和assets文件夹中的图片ic_launcher.png都
是由PathClassLoader加载的,而java.lang.String是由BootClassLoader加载的
2.泛型2.1概念泛型始现于JDK1.5,从那以后大家在项目常常使用泛型,比
如:
ArrayListGirlarrayList=newArrayListGirlfor(inti=0;
i10;
i++){Girlgirl=new
Girl();
arrayList.add(girl);
}在与此类似的场景中利用泛型限定了集合中的输入类型,
从而让编译器屏蔽了源程序中的非法数据输入,比如此时往ArrayList中add一个
Boy就无法通过编译器的编译
泛型主要是给编译器看的;
那么在编译完成之后生成的字节码里泛型会发生什么
变化呢?
来看个例子:
privatevoidtestArraylistClass(){Classclazz1=newArrayListInteger().getClass();
Classclazz2=newArrayListString().getClass();
booleanisEqual=(clazz1==clazz2);
System.out.println(“----isEqual=“+isEqual);
}输出结果:
—-isEqual=true带不同泛型的ArrayList在编译后生成的Class是相同的!
也就是
说,泛型在编译生成字节码文件时会被”擦除”;
不管ArrayList带什么泛型,在编译
后都是ArrayList所对应的字节码文件
privatevoidtestArraylistGeneric(){try{ArrayListIntegerarrayList=newArrayList
IntegerarrayList.add(9527);
arrayList.add(9528);
Method
method=arrayList.getClass().getMethod(“add”,Object.class);
method.invoke(arrayList,”hello,java”);
for(inti=0;
iarrayList.size();
i++){
System.out.println(“----arrayList.get(“+i+”)=“+arrayList.get(i));
}}catch(Exception
e){}}输出结果如下图所示:
看到了吧,之因此能把一个字符串add到该ArrayList中,究其原因还是因为泛型
的擦除所致
2.2自定义泛型方法publicstaticTTgenericMethod1(Tt){returnnull;
}publicK,V
KgenericMethod2(Kk,Vv){returnnull;
}publicK,VStringgenericMethod3(Kk,Vv)
{returnnull;
}在自定义泛型方法时,请注意在方法的返回值之前声明一个泛型,比
这就表示该方法使用到了泛型T。
在此之后,在方法的输入参数中和方法体中
均可以使用该泛型
2.3自定义泛型接口publicinterfaceUserInfoT{publicvoidprintUserInfo(T
t);
}privateclassUserInfoImplTimplementsUserInfoT{@Overridepublicvoid
printUserInfo(Tt){}}在自定义泛型接口时,请注意在接口名之后声明一个泛型,比
这就表示该接口使用到了泛型T。
在此之后,在接口定义方法时就可以使用该
泛型了
2.4自定义泛型类publicclassCollectionK,V{privateKkey;
privateVvalue;
privateKgetValue(Kk){returnnull;
}privatevoidprintValue(Vv){}}自定义泛型类
与自定义泛型接口非常类似,不再赘述
3.反射我们知道Java代码会被编译成字节码文件,当需要用一个类创建其对象的
时候就会将其对应的字节码文件装载到内层,然后新建对象。
也就是说,当一个类编译完成后,在生成的.class文件中会产生一个Class对象,
该对象用于表示这个类的信息,比如类的属性,字段,构造方法等等
既然Class中包含了这么多有用的信息,那么我们可以用什么方式获取Class呢?
3.1获取Class//第一种方式Classclazz=Girl.class;
System.out.println(“----“+
clazz.getName());
//第二种方式Girlgirl=newGirl();
clazz=girl.getClass();
System.out.println(“----“+clazz.getName());
//第三种方式clazz=
Class.forName(“com.lizi.classloaderdemo.Girl”);
三种方式:
1.利用类名.class获取2.利用对象.getClass()获取3.利用Class.forName(“类名”)获取
在获取到Class之后,就可以利用newInstance()方法生成一个对象
Objectobject=clazz.newInstance();
其实,在调用newInstance()方法时实际上是调
用了该类的无参构造方法。
当然,我们的目的不仅仅是利用newInstance()生成一个对象,更重要的是要采用
反射技术结合Class获取到该类的构造方法,属性,方法等信息
在该类中有一些简单的属性,比如年龄,姓名,国家,城市,腰围,胸围,臀
围。
还有一些简单的方法比如,构造方法Girl(Stringname,Integerage),获取电话号
码getMobile();
看到这里获取大家可能发现了:
这些属性和方法有的是公有的,有
的是私有的。
访问属性的不同会带来哪些差异呢?
带着这个小疑问,我们来看看常
见的反射使用方法
3.2获取构造方法/***利用反射获取类的构造器**1getConstructors()获取类
的构造器,但获取不到私有构造器*2getDeclaredConstructors()获取类的所有构造
器*3getDeclaredConstructor()获取指定的构造器*/privatevoidtestGetConstructor()
{try{Classclazz=Class.forName(“com.lizi.classloaderdemo.Girl”);
Constructor[]
Constructors=clazz.getConstructors();
for(Constructorconstructor:
Constructors){
System.out.println(“----constructor=“+constructor);
}System.out.println(“-----------------
-----------”);
Constructor[]declaredConstructors=clazz.getDeclaredConstructors();
for
(ConstructordeclaredConstructor:
declaredConstructors){System.out.println(“----
declaredConstructor=“+declaredConstructor);
}System.out.println(“-------------2----------
-----”);
Constructorconstructor=clazz.getDeclaredConstructor(String.class,Integer.class);
constructor.setAccessible(true);
Girlgirl=(Girl)constructor.newInstance(“liuyan”,
Integer.valueOf(22));
System.out.println(“----girl=“+girl);
}catch(Exceptione){
e.printStackTrace();
}}获取类所有的构造器,这个没啥可说的。
那么怎么获取指定的
构造器呢?
一个类可能有多个重载的构造方法,它们的方法名都是一样的;
因此此
时需要从构造器的输入参数入手,比如:
clazz.getDeclaredConstructor(String.class,Integer.class);
就可以获取到如下的构造方
法:
privateGirl(Stringname,Integerage){}但是请注意该构造方法是private的,因此需
要将该方法的accessible标志设置为true表示取消语言访问检查。
即:
constructor.setAccessible(true);
在获取构造方法后即可利用newInstance()创建对
象,即:
Girlgirl=(Girl)constructor.newInstance(“liuyan”,Integer.valueOf(22));
3.3利用反射
获取字段/***利用反射操作类的字段*1getFields()获取类的字段,但是获取不到
私有字段*2getDeclaredFields()获取类的所有字段*3获取指定的字段及其type*
4获取指定对象的某个字段值*5设置指定对象的某个字段值*/privatevoid
testGetField(){try{Classclazz=Class.forName(“com.lizi.classloaderdemo.Girl”);
Field[]fields=clazz.getFields();
for(Fieldfield:
fields){System.out.println(“----field=“
+field);
}Field[]declaredFields=clazz.getDeclaredFields();
for(FielddeclaredField:
declaredFields){System.out.println(“-----declaredField=“+declaredField);
}//获取指定
的字段及其typeFieldfield=clazz.getDeclaredField(“name”);
Classtype=
field.getType();
System.out.println(“----field=“+field+“,type=“+type);
System.out.println(“-----------------------“);
//获取指定对象的某个字段值Girlgirl=new
Girl(“lucy”,100,100,100,18);
Fieldfield2=clazz.getDeclaredField(“name”);
field2.setAccessible(true);
Stringname=(String)field2.get(girl);
name=“+name);
//设置指定对象的某个字段值Fieldfield3=
clazz.getDeclaredField(“name”);
field3.setAccessible(true);
field3.set(girl,“hanmeimei”);
System.out.println(“----girl=“+girl);
}catch(Exceptione){}}3.4利用反射获取类中
的方法/***利用反射获取类的方法*1getMethods()获取该类及其父类的方法,但
不能获取到私有方法*2getDeclaredMethods()获取该类本身所声明的所有方法*3
反射出类中的指定方法*/privatevoidtestGetMethod(){try{Classclazz=
Objectobject=clazz.newInstance();
Method[]methods=clazz.getMethods();
for(Methodmethod:
methods){
System.out.println(“----method=“+method);
}Method[]declaredMethods=
clazz.getDeclaredMethods();
for(MethoddeclaredMethod:
declaredMethods){
System.out.println(“----declaredMethod=“+declaredMethod);
}Methodmethod=
clazz.getDeclaredMethod(“getMobile”,String.class);
ClassreturnType=
method.getReturnType();
System.out.println(“----method=“+method+”,returnType=“+
returnType);
method.setAccessible(true);
Stringmobile=(String)method.invoke(object,
“678”);
System.out.println(“----mobile=“+mobile);
}catch(Exceptione){}}3.5利用
反射操作数组/***利用反射操作数组*1利用反射修改数组中的元素*2利用反
射获取数组中的每个元素*/privatevoidtestArrayClass(){int[]intArray=new
int[]{5,7,9};
Array.set(intArray,0,9527);
Classclazz=intArray.getClass();
if
(clazz.isArray()){intlength=Array.getLength(intArray);
for(inti=0;
ilength;
i++){
Objectobject=Array.get(intArray,i);
StringclassName=object.getClass().getName();
System.out.println(“----object=“+object+”,className=“+className);
}}}3.6利用反射
获取泛型的参数类型在许多框架中有这样的需求:
根据不同的泛型参数响应不同的
操作。
一说到泛型参数类型,可能大家立马就想到了刚才说的泛型擦除,比如ArrayList
在编译后就变成了ArrayList,它原本的泛型被”擦除”了。
但是我们有时确实需要知
道泛型的参数类型,又该怎么来实现呢?
按照刚才的那些思路恐怕是走不通了,得
另辟蹊径了
第一步:
定义getGenericHelper()方法其输入参数为带泛型的参数,比如ArrayList
String,Integer
第二步:
利用反射获取到该getGenericHelper()方法,即:
method=getClass().getDeclaredMethod(“getGenericHelper”,HashMap.class);
第三步:
获取到该方法的带泛型的输入参数,即:
Type[]genericParameterTypes=method.getGenericParameterTypes();
注意
getGenericParameterTypes()方法返回的是一个数组,因为方法可能有多个参数,但
是依据我们的需求这个数组中是仅有一个元素的
4.2ParameterizedTypeParameterizedType称为参数化类型,比如HashMapK,
Integer
privateHashMapK,IntegerhashMap=null;
publicvoidtestParameterizedType()
throwsE
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 推荐 下载 Android 框架 基础知识 梳理
![提示](https://static.bdocx.com/images/bang_tan.gif)