黑马程序员—反射与泛型

----------- android培训java培训、java学习型技术博客、期待与您交流! ------------


反射与泛型

反射:
反射定义: 反射就是把Java类中的各种成分(package、constructor,method,field)映射成相应的Java类.Java程序中的各个Java类属于同一个类事物, 描述这类事物的Java类就是java.lang.Class类. Class类的实例对象对应各个类在内存中的字节码.
1:获得各字节码对应的实例对象
由于Class无构造函数 所以无法直接生成对像 ,因此Class直接生成对象,只有获得字节码对应的实例对象有三种方法分别是:类名.class;对象名.getClass();
Class.forName("类的完整名称"); * 需要带上包名! 做反射时主要用这种.
下面的java就是
public class ReflectTest {
/*由于Class无构造函数 所以无法直接生成对像
Class得到的是字节码有三种方式;
1 对象直接调用getclass()
2类型直接.class
3用class.forname()得到字节码
*/

public static void main(String[] args) throws Exception {
String s="abc";

Class cla1=s.getClass();
Class cla2=String.class;
Class cla3=Class.forName("java.lang.String");
}
}


2. 九个预定义的Class实例对象.

即: 八种基本类型(boolean, byte, short, int, long, float, double, char)和void所对应的. 形如Integer.TYPE.
例如: Integer.TYPE和int.class一样, 都是int类型, 但是Integer.class却是java.lang.Integer类型.
//可以调用isPrimitive()方法可以判断是不是八大基本类型
System.out.println(cla1.isPrimitive());


3. Constructor类,

下面就用代码展现构造方法的反射应用:
import java.lang.reflect.Constructor;

class Test2
{
public static void main(String [] args) throws Exception
{
//反射获得接收StringBuffer的构造方法
Constructor constructor1 = String.class.getConstructor(StringBuffer.class);

//是接收StringBuffer的构造方法, 所以要传入StringBuffer对象
String str = (String)constructor1.newInstance(new StringBuffer("abc"));

System.out.println(str);
System.out.println(str.charAt(2));
}

}

import java.lang.reflect.Constructor;

class Test2
{
public static void main(String [] args) throws Exception
{
//反射获得接收StringBuffer的构造方法
Constructor constructor1 = String.class.getConstructor(StringBuffer.class);

//是接收StringBuffer的构造方法, 所以要传入StringBuffer对象
String str = (String)constructor1.newInstance(new StringBuffer("abc"));

System.out.println(str);
System.out.println(str.charAt(2));
}

}



4. Field类


下面介绍成员变量的反射应用:


import java.lang.reflect.Field;

class Test2
{
public static void main(String [] args) throws Exception
{
ReflectPoint pt1 = new ReflectPoint(3, 5);


Field fieldY = pt1.getClass().getField("y"); //getField()方法只能获取可见的
Field fieldX = pt1.getClass().getDeclaredField("x"); //getDeclaredField()方法连不可见的也能获取(此处x是private修饰的)

//fieldY不是对象身上的变量, 而是类, 若果要取值需要指定取哪个对象的
System.out.println(fieldY.get(pt1));

//由于Reflect的x变量是私有的, 不可见, 所以这里要先setAccessible(true), 之后才能访问. * 这叫暴力反射!
fieldX.setAccessible(true);
System.out.println(fieldX.get(pt1));

}

}

import java.lang.reflect.Field;

class Test2
{
public static void main(String [] args) throws Exception
{
ReflectPoint pt1 = new ReflectPoint(3, 5);


Field fieldY = pt1.getClass().getField("y"); //getField()方法只能获取可见的
Field fieldX = pt1.getClass().getDeclaredField("x"); //getDeclaredField()方法连不可见的也能获取(此处x是private修饰的)

//fieldY不是对象身上的变量, 而是类, 若果要取值需要指定取哪个对象的
System.out.println(fieldY.get(pt1));

//由于Reflect的x变量是私有的, 不可见, 所以这里要先setAccessible(true), 之后才能访问. * 这叫暴力反射!
fieldX.setAccessible(true);
System.out.println(fieldX.get(pt1));

}

}下面是例子中用到的ReflectPoint类: [java]
public class ReflectPoint {

private int x;
public int y;

public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}

}

public class ReflectPoint {

private int x;
public int y;

public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}

}



5.Method类

下面介绍成员方法的反射:

调用方法的invoke(obj, args)执行, 如果第一个参数为null, 就说明是调用的静态方法.


[java]
import java.lang.reflect.Method;

public class Test3 {

public static void main(String[] args) throws Exception{

String str = "asdf";

Method methodCharAt = String.class.getMethod("charAt", int.class);
char c = (char)methodCharAt.invoke(str, 2);

System.out.println(c);
}

}

import java.lang.reflect.Method;

public class Test3 {

public static void main(String[] args) throws Exception{

String str = "asdf";

Method methodCharAt = String.class.getMethod("charAt", int.class);
char c = (char)methodCharAt.invoke(str, 2);

System.out.println(c);
}

}




6.暴力反射
* 暴力反射: 反射获取Field时, 对于可见的Field直接用getField(...)方法即可; 对于不可见的Field要使用getDeclaredField(..)获得Field对象, 然后调用Field对象的setAccessible(true)之后才能获取. 这叫做暴力反射.

下面代码:

//会报错 因为无权限 但使用暴力反射可以解决 得到声明过得变量
Field f2=rp1.getClass().getDeclaredField("x");

//f1得到的是类上的字节码 不是对象上的
//通过修改权限
f2.setAccessible(true);
System.out.println(f2.get(rp1));



下面就开始讲泛型的应用


泛型

1、泛型的由来:

(1)泛型的出现将运行时期的问题ClassCastException 转移到了编译时期变成了编译失败。
(2)泛型的出现避免了类型强制转换的麻烦。
(3)泛型技术是用在编译时期的技术。
(4)泛型的出现提高了类型的安全性。

其实泛型:就是当类型不确定的时候,定义<变量>用来接收指定的类型,要使用什么类型就将什么类型传递进来即可。
2、泛型应用的综合案例:

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

class Test2
{
public static void main(String [] args) throws Exception
{
HashMap<String, Integer> maps = new HashMap<String, Integer>();
maps.put("zxx", 28);
maps.put("lhm", 35);
maps.put("flx", 33);

Set<Map.Entry<String, Integer>> entrySet = maps.entrySet();
for(Map.Entry<String, Integer> entry: entrySet){
System.out
.println(entry.getKey() + ":" + entry.getValue());
}

}
}

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

class Test2
{
public static void main(String [] args) throws Exception
{
HashMap<String, Integer> maps = new HashMap<String, Integer>();
maps.put("zxx", 28);
maps.put("lhm", 35);
maps.put("flx", 33);

Set<Map.Entry<String, Integer>> entrySet = maps.entrySet();
for(Map.Entry<String, Integer> entry: entrySet){
System.out
.println(entry.getKey() + ":" + entry.getValue());
}

}
}


3、自定义泛型方法

private static <T> add(T x,T y){
return null;
}

上面的方法接受两个T型参数, 返回一个T型的值. (不能接受子类)
其中的T只能代表引用类型, 不能代表基本类型. 例如: T可以不能代替int,但可以代替由int自动装箱来的Integer.
用于放置泛型的类型参数的尖括号应出现在其他所有修饰符之后和在方法的返回类型之前,也就是紧邻返回值之前。按照惯例,类型参数通常用单个大写字母表示。

伟大的Java还支持上限通配符<? extends Type>, 表示必须是Type本身或其子类; 下限通配符<? super Type>, 表示必须是Type本身或其父类。


----------- android培训java培训、java学习型技术博客、期待与您交流! ------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值