您的位置:首页 > 编程语言 > Java开发

java自学笔记之java高新技术

2014-01-21 17:12 232 查看

Java高新技术:

import static java.lang.math.*; //静态导入

overload:重载   

override:重写

可变参数: ...;当成数组。

高级for循环:只适合取数据。

自动装箱拆箱:Integer对象在-128 ~ 127之间的对象是相等的。这是一种设计模式,享元模式,flyweight节约内存

枚举: 

public enum WeekDay{
SUN(0),MON(1),TUE(2),WED(3),THT(4),FRI(5),SAT(6)
private WeekDay() {};
private String value;
public WeekDay(value){
this.value = value;

}
public String getValue()
{
return this.value;
}
private WeekDay(int day) {};

}

public enum TrafficLamp{
RED(30){
public TrafficLamp nextLamp()
return GREEN;
}
GREEN(45){
public TrafficLamp nextLamp()
return YELLEO;
}
RED(15){
public TrafficLamp nextLamp()
return RED;
}
public abstract TrafficLamp nextLamp();

private int time;

private TrafficLamp(int time){
this.time = time;
}

}

枚举如果只有一个值就相当于用单台设计模式定义出一个类。

反射的基石 Class类

获得字节码:类名。class  ;对象。getClass ; Class。forName("");

//获得构造方法:

Constructor[] constructors = Class.forName("").getConstructors();

或获取一个 Constructor constructor = Class.forName("").getConstruector(xx.class);

//创建实例对象:

String str = (String) constructor.newInstance(new xx(""));

//跳过构造方法直接获取实例对象:(用缓存保存)

Stirng str = (String)Class.forName("").newInstance();

//获取字段

Field [] fields =  obj.getClass().getFields();

for(Field field : fields)

{
if(field.getType() == String.class())
{
String oldValue = (String)field.get(obj);
String newValue = (String)field.replace('','');
field.set(obj,newValue);
}

}

//获取成员方法

Method method = String.class.getMethod("方法名",参数字节码);

method.invoke(对象,参数);

//反射执行类中的main方法

mainMethod.invok(null,new Object[]{new String[]{"xxx"}});

//数组的反射:

hashCode():哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。hashCode方法实际上返回的就是对象存储的物理地址.

反射实现框架功能:

以前开发的框架可以通过反射调用现在开发的程序。

建一个properties文件。然后读取这个文件的键值对。

InputStream is = new FileInputStream("config.properties");

//properties的加载路径变化

//InputStream is = ReflectTest.class.getClassLoader().getResourceAsStream("com/youxiang/config.properties")

//或者是InputStream is = ReflectTest.class.getResourceAsStream("config.properties");

Properties prop = new Properties();

prop.load(is);

prop.close();

String className = prop.getProperties("className");

Collection collections = (Collection)Class.forName(className);

内省IntorSpector:

主要是对Java Bean属性、方法等的一种处理方法

//PropertyDescriptor来设置和获取值

ReflectPoint rp = new ReflectPoint(3,5);

String propertyName = "x";

PropertyDescriptor pd = new PropertyDescriptor(propertyName,rp.getClass());

Method methodGetX = pd.getReadMethod();

Object retVal = methodGetX.invoke(rp);

//BeanInfo 的 Introspector 来设置和获取值

BeanInfo. beanInfo = Introspector.getBeanInfo(Person.class);

PropertyDescriptors [] pds = beanInfo.getPropertyDescriptors();

for(PropertyDescriptor pd : psd)

{
if(pd.getName().equals(propertyName))
{
Method methodGetX = pd.getReadMethod();
retVal = nethodGetX.invoke(pt);
break;
}

}

//Beanutils工具包来设置和获取值:

需要先将jar包下载导入到工程

BeanUtils.getProperty(rp,"x").getClass().getName();

BeanUtils.setProperty(rp,"x","9");

//操作map

Mao map = new HashMao();

map.put("name","youxiang");

BeanUtils.populate(bean,map);

BeanUtils默认只能转换八种默认数据类型,

如Date类型就不能转换set值。需要注册一个日期转换器,实现Coverter()接口

ConvertUtils.register(new Converter(){
public Object convert(Class type,Object value){
if (value == null) {
return null;
}
if (!(vlaue instanceof String)) {
throw new ConversionException("只支持String类型");
}
String str = (String) value;
if (str.trim().equals("")) {
return null;
}
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
return df.parse(str);
}

},Date.class);

//java7的新特性

Map map={name:"zxx",age:18};

BeanUtils.setProperty(map,"name","1=hm");

注解:annotation

相当于一种标记,Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。

@Deprecated:表示子类要重写(override)父类的对应方法

@Override:表示方法是不建议被使用的。

@SuppressWarnings:表示抑制警告

自定义注解:

 Java中提供了四种元注解,专门负责注解其他的注解

 @Retention元注解,表示需要在什么级别保存该注释信息(生命周期)。可选的RetentionPoicy参数包括:

 RetentionPolicy.SOURCE: 停留在java源文件,编译器被丢掉

 RetentionPolicy.CLASS:停留在class文件中,但会被VM丢弃(默认)

 RetentionPolicy.RUNTIME:内存中的字节码,VM将在运行时也保留注解,因此可以通过反射机制读取注解的信息

 @Target元注解,默认值为任何元素,表示该注解用于什么地方。可用的ElementType参数包括

 ElementType.CONSTRUCTOR: 构造器声明

 ElementType.FIELD: 成员变量、对象、属性(包括enum实例)

 ElementType.LOCAL_VARIABLE: 局部变量声明

 ElementType.METHOD: 方法声明

 ElementType.PACKAGE: 包声明

 ElementType.PARAMETER: 参数声明

 ElementType.TYPE: 类、接口(包括注解类型)或enum声明

 @Documented将注解包含在JavaDoc中

 @Inheried允许子类继承父类中的注解

 

泛型:

是提供給javac编译器使用的,用于限定输入的类型。

用泛型时,如果两边都是用到泛型,两边必须要一样的泛型。

Map<Integer,String> map = new HashMap<Integer,String>();

map.put(1, "aa");

map.put(2, "bb");

map.put(3, "cc");

Set<Map.Entry<Integer, String>> set1 = map.entrySet();

for(Map.Entry<Integer, String> entry: set1){
Integer key = entry.getKey();
String value = entry.getValue();
System.out.println(key+".."+value);

}

1,整个ArrayList<E>称为泛型类型

2,ArrayList<E>中的E称为类型变量或类型参数3,整个ArrayList<Integer>称为参数化的类型

4,ArrayList<Integer>中的Integer称为类型参数的实例或实际类型参数。

5,ArrayList<Integer>中的<>念着typeof

6,ArrayList称为原始类型

参数化类型和原始类型是具有兼容性的:Vector<String> c = new Vector();

原始类型可以引用一个参数化类型的对象:Vector c = new Vector<String>();

参数化类型不考虑继承关系。错误:Vector<String> v = new Vector<Object>();

编译器不允许创建参数化类型数组。错误:Vector <Integer> v[] = new Vector<Integer>[20];

通配符:'?'只能对变量进行引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法。

向上限定:?extends Number:?或者?的子类;

向下限定:?super Integer :?的父类或者?。

自定泛型:

在方法上定义一个泛型,格式是在返回值前加上“<泛型变量名称>”;public static <T> void doxx(T t);

只有引用类型才能作为泛型方法的实际参数,如String Integer等,基本数据类型如int等不能

泛型也可以使用在异常中。

类型推断:定义的泛型方法代表返回两者的最大公约数:

静态方法使用的泛型只能是定义在方法上的。

//编写一个泛型方法,实现指定位置上的数组元素的交换。

public <T> void swap(T arr[],int pos1,int pos2){
T temp = arr[pos1];
arr[pos1] = arr[pos2];
arr[pos2] = temp;

}

//编写一个泛型方法,接受一个任意数组,颠倒数组输出。

public <T>void reverse(T arr[]){
int  start = 0;
int  end = arr.length-1;

while(true){
if (start>=end) {
break
}
T temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;

start++;
end--;
}

}

如何通过反射获得泛型的参数化类型:

Method generMethod = GenericTest.class.getMethod("genericTypeApp", ArrayList.class);

Type[] genericType = generMethod.getGenericParameterTypes();

System.out.println(genericType[0]);

System.out.println(generMethod.getParameterTypes()[0]);

public static void genericTypeApp(ArrayList<String> a){}

类加载器:ClassLoader

类加载器负责把类加载到Java虚拟机(JVM)中。指定类的名称,类加载器就会定位这个类的定义,每一个Java类必须由类加载器加载。

启动JVM的时候,可以使用三个类加载器:引导(bootstrap)类加载器(第一个加载器它不是java类)、扩展(extensions)类加载器、应用程序(application)类加载器。

得到类加载名称:类.class.getClassLoader().getClass().getName();

当处理类加载器时,父委托模式是一个需要理解的关键概念。它规定:类加载器在加载自己的类之前,可以委托先加载父类。

父类加载器可以是客户化的类加载器或者引导类加载器。但是有一点很重要,类加载器只能委托自己的父类加载器,而不能是子类加载器(只能向上不能向下)。

全盘负责 委托机制

classloader 加载类用的是全盘负责委托机制。

全盘负责:即是当一个classloader加载一个Class的时候,这个Class所依赖的和引用的其它Class通常也由这个classloader负责载入。

委托机制:先让parent(父)类加载器寻找,只有在parent找不到的时候才从自己的类路径中去寻找。

类加载还采用了cache机制:如果cache中保存了这个Class就直接返回它,如果没有才从文件中读取和转换成Class,并存入cache,这就是为什么修改了Class但是必须重新启动JVM才能生效,并且类只加载一次的原因。

自定义类加载器:

1、 自定义的类加载器必须继承ClassLoader。

2、 ClassLoader中有loadClass()和findclass()两个方法,loadClass()方法实现了委托机制,findClass()方法辅负责自己加载类,因此我们只需重写findClass()方法

3、 defineClass()方法。通过findClass()得到class文件中的二进制数据后,用findClass()方法将其转换为字节码。

代理和动态代理:

动态代理: JVM可以在运行期动态生成类的字节码,这种动态生成往往被用作代理类,即为动态代理.

jvm生成的动态类必须实现一个或多个接口,所以,jvm生成的动态类只能用作具有相同接口的目标类的代理。

其实动态代理机制最核心的就是InvocationHandler(调用处理器)这个接口InvocationHandler 是代理实例的调用处理程序 实现的接口。

代理对象:代理类所生成的对象。

目标对象:代理类所代理的那个类生成的对象。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 高新技术