jdk1.5新特性:
1、静态导入
package jdk_5new;
/**
* 静态导入是jdk1.5新特性,可以直接导入类中的静态方法
*/
import static java.lang.Math.max;
import static java.lang.Math.abs;
public class StaticImport {
public static void main(String[] args) {
System.out.println(Math.max(3,8));
System.out.println(Math.abs(-21));
}
}
2、可变参数(参数个数不确定)
oveload与override(当父类一个方法定义为private,子类中定义一个与之相同的方法,算不算是重写呢?不算!算是一个全新的方法)
package jdk_5new;
/**
* @author Administrator
*
*/
public class VariableParameter {
public static void main(String[] args) {
System.out.println(add(2,3));
System.out.println(add(2,3,4));
}
public static int add(int x, int...args){
int sum = x;
for(int i=0;i<args.length;i++){
sum = sum+args[i];
}
return sum;
}
}
3、增强的for循环
package jdk_5new;
public class ExtendedFor {
public static void main(String[] args) {
System.out.println(add(2, 3));
System.out.println(add(2, 3, 4));
}
public static int add(int x, int... args) {
int sum = x;
for (int arg:args) {
sum = sum + arg;
}
return sum;
}
}
4、自动装箱与拆箱(-128~127 享元模式 flyWeight)
package jdk_5new;
public class AutoBox {
public static void main(String[] args) {
//自动装箱
Integer num = 3;
//自动拆箱
int sum = num +2;
System.out.println(sum);
Integer num1 = 13;
Integer num2 = 13;
Integer num3 = 128;
Integer num4 = 128;
String s1 = new String("abc");
String s2 = new String("abc");
System.out.println("num1 == num2:"+(num1 == num2));
System.out.println("num3 == num4:"+(num3 == num4));
//s1 == s2 比较的是两个对象的地址
System.out.println("s1 == s2 :"+(s1 == s2));
//这里String的equals方法被重写了,比较的是两个对象的值
System.out.println("s1.equals(s2): "+s1.equals(s2));
}
/**
* 装箱如果数字在-128~127的这些数字,一旦被装箱成Integer对象之后,就会被缓存起来
* 缓冲在一个池里面,到下次如果遇到又要把它封装成对象的时候,先看池子里面有没有,
* 如果有直接从池里面拿出来。因为我觉得小的整数用的频率会非常高,并且经常不会改变。
* 所以就 用一个池存起来,实现重用。
* (享元模式)经常用到的小对象,不会每次都创建!而是放到一个对象池里面。
*/
}
5、枚举
为什么要有枚举?问题:要定义星期几或性别的变量,该怎么定义?枚举就是让某个类型的变量只能为若干个固定值中的一个,否则编译
器就会报错。
package jdk_5new;
public class Enum_1 {
public static void main(String[] args) {
//编译时就发现你输入的值不合法
Week WeekDay = Week.FRI;
//打印一个对象,其实就是打印他的toString
System.out.println(WeekDay);
System.out.println(WeekDay.nextDay());
//通过匿名内部类的方式将众多的if...else分解到不同的方法中。
Week2 week2 = Week2.MON;
System.out.println(week2);
System.out.println(week2.nextDay());
}
}
package jdk_5new;
public class Week {
private Week(){
}
public final static Week SUN = new Week();
public final static Week MON = new Week();
public final static Week TUE = new Week();
public final static Week WEN = new Week();
public final static Week THU = new Week();
public final static Week FRI = new Week();
public final static Week SAT = new Week();
public Week nextDay(){
if(this == SUN){
return MON;
}else if(this == MON){
return TUE;
}else if(this == TUE){
return WEN;
}else if(this == WEN){
return THU;
}else if(this == THU){
return FRI;
}else if(this == FRI){
return SAT;
}else if(this == SAT){
return SUN;
}else
return MON;
}
/**
* 如果没有重写这个toString方法,打印就会有问题。打印Week对象时,会调用这个方法。
* 打印一个对象,就是打印他的toString
*/
public String toString(){
if(this == SUN){
return "今天是星期天!";
}else if(this == MON){
return "今天是星期一!";
}else if(this == TUE){
return "今天是星期二!";
}else if(this == WEN){
return "今天是星期三!";
}else if(this == THU){
return "今天是星期四!";
}else if(this == FRI){
return "今天是星期五!";
}else{
return "今天是星期六!";
}
}
}
6、反射(反射不是jdk1.5的新特性,而是jdk1.2就开始有了)
package jdk_5new;
import java.lang.reflect.*;
import java.util.Arrays;
/**
*
* @author Administrator Class---->代表一种什么样的事物? Person person1 = new Person();
* Person person2 = new Persion();
*
* Class cls1 = new Class()??? 没有这种方法, Class cls2 = ;
*
* Class 实例对象代表内容里的一份字节码
*
* Class cls1 = Date.class //字节码1 Class cls2 = Person.class //字节码2
*
* getClass(); 得到这个类的字节码 Class.forName("java.lang.String");
*
* 得到一个类的字节码有两种方式 : 第一种:这个类的字节码已经加载到内存中,此时直接返回就可以了;
* 第二种:虚拟机中还没有这个类的字节码,于是用类加载器去加载。
* 加载后就把这个类的字节码缓存起来,同时用Class.forName()这个方法 返回刚才加载的字节码
*
* 如何得到各个字节码对应的实例对象?(Class类型) 有三种方法: 1、类名.class,如 System.class
* 2、实例名.class,如 new Date().getClass 3、Class.forName("类名"),如
* Class.forName("java.lang.String");
* 反射的时候最常用的是第三种,因为在写源程序的时候,并不知道要创建实例的类的名称,
* 而是在运行的时候才将类的类型传进来。比如从配置文件里面读取。
*
*/
public class ClassDemo {
public static void main(String[] args) throws Exception {
/**
* Class 类的实例表示正在运行的 Java 应用程序中的类和接口。 枚举是一种类,注释是一种接口。每个数组属于被映射为 Class
* 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java
* 类型8个(boolean、byte、char、short、 int、long、float 和 double)和关键字 void 也表示为
* Class 对象。
*/
System.out.println(void.class);
System.out.println(int.class);
/**
* 用各各方式,得到的是内存中同样一份字节码
*/
String str1 = "abc";
Class cls1 = str1.getClass();
Class cls2 = String.class;
Class cls3 = Class.forName("java.lang.String");
System.out.println(cls1 == cls2);
System.out.println(cls2 == cls3);
System.out.println(cls1 == cls3);
// isPrimitive() 判定指定的 Class 对象是否表示一个基本类型。
System.out.println(cls1.isPrimitive()); // false
System.out.println(int.class.isPrimitive()); // true
System.out.println(int.class == Integer.class); // false
/*
* Object.TYPE 表示所包装的那个基本类型的字节码 static Class<Integer> TYPE 表示基本类型 int 的
* Class 实例。
*/
System.out.println(int.class == Integer.TYPE); // ture
System.out.println(int[].class);
System.out.println(int[].class.isPrimitive());
System.out.println(Array.class);
System.out.println(int[].class.isArray());
// 总之,只要是在程序中出现的类型,都有各自的Class实例对象,例如int[],void
// new String(new StringBuffer("abc"))
Constructor cons1 = String.class.getConstructor(StringBuffer.class);
String str = (String) cons1.newInstance(new StringBuffer("abc"));
// Field 成员变量
ReflectPoint reflectp1 = new ReflectPoint(3, 5);
ReflectPoint reflectp2 = new ReflectPoint(4, 8);
// FieldY不是对象上的变量,而是类上的变量,它去取某个对象上对应的值
Field fieldY = ReflectPoint.class.getField("y");
System.out.println(fieldY.get(reflectp1));
System.out.println(fieldY.get(reflectp2));
// 对私有成员的反射取值
Field fieldX = ReflectPoint.class.getDeclaredField("x");
// 暴力反射
fieldX.setAccessible(true);
System.out.println(fieldX.get(reflectp2));
changeStrValue(reflectp1);
System.out.println(reflectp1);
// 成员方法反射Method
Method methodCharAt = String.class.getMethod("charAt", int.class);
// invoke 列车司机把列车停下来,但并不是司机真正把它停下来。而是列车员踩刹车,
// 给列车发信号,列车自已开启自己的制动系统让自己停下来。所以只有火车自己才更清楚该
// 怎么停下来!String也是,String调用自己的invoke方法截取字符
System.out.println(methodCharAt.invoke(str1, 1));
// 如果第一个参数为null,意味着这个method为静态方法
// System.out.println(methodCharAt.invoke(null,1));
// 1、直接用静态代码的方式调用main
TestArguments.main(new String[] { "111", "222", "333" });
// 2、用反射的方式调用main,为什么要用反射的方式调用?我不知道调用哪个类的main方法,而是以参数传入
String startingClassName = args[0];
Method mainMethod = Class.forName(startingClassName).getMethod("main",
String[].class);
// jdk1.4不把数组而是一个参数,而是当成三个参数
mainMethod.invoke(null, new Object[] { new String[] { "aaa", "bbb",
"ccc" } });
// 哥们,我给你的是一个Object,而不是数组,不要给我拆包啊
mainMethod.invoke(null, (Object) new String[] { "aaa", "bbb", "ccc" });
// 数组的Class类型
int[] a1 = new int[3];
int[] a2 = new int[4];
int[][] a3 = new int[2][3];
String[] a4 = new String[3];
String[] a5 = new String[] { "a", "b", "c" };
int[] a6 = new int[] { 1, 2, 3 };
Integer[] a7 = new Integer[] { 1, 2, 3 };
System.out.println(a1.getClass() == a2.getClass());
System.out.println(a3.getClass().getName());
System.out.println(a1.getClass().getSuperclass().getName());
// 打印数组
System.out.println(Arrays.asList(a5));
/*
* 1.4中没有可变参数,asList中只能是对象(Object)类型,于是自动匹配1.5的asList asList(T...a)
* 这种可变参数的形式,虚拟机就会把int数组当成是一个参数
*/
System.out.println(Arrays.asList(a6));
System.out.println(Arrays.asList(a7));
int []a8 = new int[]{1,2,3,4,5};
printObject(a8);
printObject("abc");
//Object里面可以放不同类型的数据哦!
Object[] a9 = new Object[]{"a",1};
System.out.println(a9[0].getClass().getName());
System.out.println(a9[1].getClass().getName());
}
/**
*
* @param obj
* @throws Exception
* 需求:通过反射将一个对象中的成员变量值换掉
*/
public static void changeStrValue(Object obj) throws Exception {
Field[] fields = obj.getClass().getFields();
for (Field field : fields) {
// 相同的Class类型(字节码)都是一份,比较用"=="
if (field.getType() == String.class) {
String oldStr = (String) field.get(obj);
String newStr = oldStr.replace('b', 'a');
field.set(obj, newStr);
}
}
}
// 数组也是一个对象,是一个特殊的对象
public static void printObject(Object obj) {
Class clazz = obj.getClass();
if (clazz.isArray()) {
int len = Array.getLength(obj);
for (int i = 0; i < len; i++) {
System.out.println(Array.get(obj, i));
}
}else{
System.out.println(obj);
}
}
}
// 自己写程序,调用人家的main方法
class TestArguments {
public static void main(String[] args) {
for (String arg : args) {
System.out.println(arg);
}
}
}
7、泛型 泛型在函数体本身不明确其参数类型,而是在创建对象的时候指定参数具体指定的类型。这样就可以在函数内部不用强制类型转换,并且将
可能在运行阶段出现的问题在编译阶段就暴露出来。
package generic;
import java.io.Serializable;
import java.util.*;
/**
* 泛型类型的确定:
* 1、输入参数什么类型就是什么类型
* 2、多个输入参数不同类型时,取多个参数的公共父类的类型
* 3、有返回值(并且有显示接收返回值)泛型变量值以返回值类型为准。
* @author Administrator
*
* @param <T>
*/
public class GenericTest2{
public static void main(String[] args) {
Demo<String> d = new Demo<String>();
// 泛型的真实类型,取他们共同的父类
//类型变量根据输入参数确定的例子
add(3, 5);
add(3.5, 5);
add(3, "abc");
Object obj = "abc";
//接收返回值的是什么类型我就返回什么类型
//泛型变量根据返回值类型确定的例子
String str = autoConvert(obj);
//此时T为Integer
//Integer n = autoConvert(obj);
//此时T没指定返回原始类型
System.out.println(autoConvert(obj).getClass());
}
public static <M> M add(M x, M y) {
return null;
}
public static <T> T autoConvert(Object obj){
return (T)obj;
}
public static <T> void fillArray(T[]a,T obj){
for(int i=0;i<a.length;i++){
a[i] = obj;
}
}
//Collection<Object> != Collection<Integer>
//泛型是不识别父类子类的,严格相等才是相等的。
//这里的?是指Collection里面可以放什么类型的元素
public static void printCollection(Collection <?> collection){
for(Object obj:collection){
System.out.println(obj);
}
}
//任意类型打印,用?也可以,用类型变量<T>也行,但T更灵活
public static <T>void printCollection2(Collection <T> collection,T t){
for(Object obj:collection){
System.out.println(obj);
}
collection.add(t);
}
public static <T> void copy1(Collection<T> c,T []src){
}
public static <T> void copy2(T[] dest,T[] src ){
}
}
// 泛型的类型只能引用类型作为实际参数,而不能用基本类型
class Demo<T extends Serializable> {
}
8、注释 annotation
package annotation;
import java.util.Arrays;
@ItcastAnnotation(value = "abc", arrayAttr = 2, annotationAttr = @MetaAnnotation("zhougang"))
public class AnnotationTest {
@SuppressWarnings("deprecation")
@ItcastAnnotation(value = "abc", arrayAttr = { 0 })
public static void main(String[] args) {
System.runFinalizersOnExit(true);
if (AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class)) {
ItcastAnnotation annotation = (ItcastAnnotation) AnnotationTest.class
.getAnnotation(ItcastAnnotation.class);
ItcastAnnotation annotation1 = (ItcastAnnotation) AnnotationTest.class
.getAnnotation(ItcastAnnotation.class);
// 注解
System.out.println(annotation);
System.out.println(annotation.color());
System.out.println(annotation.value());
System.out.println(annotation.arrayAttr().length);
System.out.println(annotation.lamp().nextLamp().name());
System.out.println(annotation.annotationAttr().value());
}
}
}