java高新技术(1)
2015-06-09 14:53
525 查看
java高新技术(1)
一、jdk1.5的新特性
(1)静态导入我们通常熟悉的import语句可以导入一个类或者是某个包下面的所有的类,而静态导入import static 是导入一个类中的某个静态方法,变量,常量或者是全部的静态方法,变量,常量。
比如说程序中要使用到Math类里面的PI常量那么就可以在类的开头将PI常量进行静态的导入了
import static java.lang.Math.PI;
(2)可变参数
我们在实际的开发中可能遇到这样的一个问题就是一个方法要接收若干个参数,但是参数的个数不确定。
可变参数的特点:
只能出现在参数列表的最后;...位于变量类型和变量名之间,前后有无空格都可以;调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。
现在想象这样的一个需求就是让你写一个方法计算两个数相加,计算三个数相加,计算四个数相加那么你就自然而然的写了下面的三个方法
public int add(int x,int y)
public int add(int x,int y,int z)
public int add(int x,int y,int m,int n)
上面三个方法方法名称相同,参数的个数不同这是重载的一种方式,重载的特点方法名一样但是参数的类型和个数不一样,返回值的类型可以相同也可以不同,一定注意的是不能以返回值类型和有无返回值作为重载函数的区别。
提到重载就顺便提一下重写
如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。在Java中,子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。
若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。
子类函数的访问权限不能小于父类,同时要特别注意的是如果满足了上面的条件但是父类中方法是被private修饰的那么子类中定义的方法不是重写而是自己定义的方法。
现在我们回到那个可变参数的话题如果现在的需求又变了呢要你计算传入的5个数的和呢,这时我们就把那个方法参数列表改造为可变参数类型的。
public int sum(int ...args)方法体里面遍历数组即可。
(3)基本数据类型的装箱和拆箱
我们都知道基本数据类型有8中就是byte short int long char boolean float double
其对应的应用数据类型是 Byte Short Integer Long Character Boolean Float Double
Integer i = 5; 是基本数据类型转换为引用数据类型,是自动的装箱
int b = i; 是引用数据类型转换为基本数据类型,是自动的拆箱
<span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;">public class HeiMaTest { public static void main(String[] args) throws Exception { Integer i = 9; Integer j = 9; System.out.println(i==j); Integer m = 128; Integer n = 128; System.out.println(m==n); } }</span></span></span></span>运行效果截图
为什么前后的结果会出现不一样的情况呢,主要java的自动的拆箱被装箱使用了一种设计模式就是享元设计模式如果有很多很小的对象他们有很多相同的东西就把它变成一个对象,把不同的东西作为外部的东西,作为方法的参数传入。
具体到上面就是在1个字节之内的整数-128到127,他们之前在内存中存在过java就把他们给缓存起来,因为大的整数不常用就没有缓存。
(4)枚举
枚举就是让某个类型的变量取值只能为若干个固定值中的一个,否则编译器就会报错,枚举可以让编译器在编译时就控制程序中非法值,普通的变量无法在开发阶段实现这一目标。
用类来模拟枚举功能
首先要有私有的构造方法,其次每个元素分别用一个公有的静态成员变量表示,可以有若干个公共方法或抽象方法。
模拟类WeekDay
<span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;">public abstract class WeekDay { private WeekDay(){} public abstract WeekDay nextDay(); public final static WeekDay MON = new WeekDay(){ @Override public WeekDay nextDay() { return SUN; } }; public final static WeekDay SUN = new WeekDay(){ @Override public WeekDay nextDay() { return MON; } }; public String toString() { return this==SUN?"SUN":"MON"; }; }</span></span></span></span>测试类
<span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;">public class HeiMaTest { public static void main(String[] args) throws Exception { WeekDay weekDay = WeekDay.MON; System.out.println(weekDay.nextDay()); } }</span></span></span></span>测试截图
上面我们是使用类模拟了枚举,下面我们使用java中自带的枚举类来探究一下枚举
<span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;">public class HeiMaTest { public static void main(String[] args) throws Exception { WeekDay weekDay = WeekDay.FRI; //显示枚举值的位置 System.out.println(weekDay.ordinal()); //获取枚举类的名称 System.out.println(weekDay.name()); //根据字符串转换为对应的枚举类型 System.out.println(WeekDay.valueOf("SUN")); //获取全部的枚举,以数组的形式返回,这里打印下数组的大小 System.out.println(WeekDay.values().length); } private enum WeekDay{ SUN,MON,TUE,WED,THU,FRI,SAT; } }</span></span></span></span>运行效果截图
上面我们使用了enum关键字来定义枚举类,那么既然是类那就有构造方法了下面我们来体验下带构造方法的枚举类
<span style="font-size:14px;"><span style="font-size:14px;">public class HeiMaTest { public static void main(String[] args) throws Exception { WeekDay weekDay = WeekDay.SUN; } private enum WeekDay{ SUN(1),MON(),TUE,WED,THU,FRI,SAT; //枚举类中方法等必须放在枚举对象后面 private WeekDay(){ System.out.println("我是无参数的构造方法"); } private WeekDay(int i){ System.out.println("我是有参数的构造方法"); } } }</span></span>运行的效果截图
上面我们体验了使用带参数的构造方法,下面我们来学习一下一个更加复杂的枚举类带抽象方法
<span style="font-size:14px;"><span style="font-size:14px;">public class HeiMaTest { public static void main(String[] args) throws Exception { WeekDay weekDay = WeekDay.SUN; System.out.println(weekDay.nextDay()); } private enum WeekDay{ SUN(1){ @Override public WeekDay nextDay() { return MON; } }, MON(2){ @Override public WeekDay nextDay() { return TUE; } }, TUE(3){ @Override public WeekDay nextDay() { return WED; } }, WED(4){ @Override public WeekDay nextDay() { return THU; } }, THU(5){ @Override public WeekDay nextDay() { return FRI; } }, FRI(6){ @Override public WeekDay nextDay() { return SAT; } }, SAT(7){ @Override public WeekDay nextDay() { return SUN; } }; private int number; //枚举类中方法等必须放在枚举对象后面 private WeekDay(int number){ this.number = number; } private WeekDay(){} public abstract WeekDay nextDay(); } }</span></span>我们要想调用WeekDay中的抽象方法那么我们必须要创建其子类的实例对象,以SUN(1){}为例就是创建了子类的实例然后调用了父类的有参数的构造方法,重写了父类的nextDay方法。
(5)泛型
在JDK的1.5中的集合类希望你在定义集合时,明确表示你要向集合中装哪种类型的数据,指定了之后你就无法加入指定类型以外的数据了。
同时需要的注意的是泛型是提供给Javac编译器使用的,可以限定集合中的输入类型让编译器挡住源程序中的非法输入,而编译器在编译带类型说明的集合时会除掉类型信息,使程序的运行效率不受影响。由于编译生成的字节码会去掉泛型类型,只要能跳过编译器就可以往某个泛型集合中加入其它类型的数据,例如,用反射得到集合再调用其add方法。
参数类型与原始数据类型的兼容性
参数类型可以引用一个原始类型的对象,编译器报警告,例如
Collection<String> c = new Vector()
原始类型可以引用一个参数化类型对象,编译报警告,例如
Collection c = new Vector<String>();
参数类型不考虑类型参数的继承关系下面的两种情况都是错误的
A.Vector<String> v = new Vector<Object>
B.Vector<Object> v = new Vector<String>
还有就是创建数组实例时,数组的元素不能使用参数化类型的
注意下面的代码是不会报错的
Vector v = new Vector<String>(); Vector<Object> v1 = v;
泛型中通配符?
使用?号通配符可以引用其他各种参数化的类型,?通配符定义的变量主要作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法。
限定通配符的上边界
Vector<? extends Number> x = new Vector<Integer> Integer是Number的子类
限定通配符的下边界
Vector<? super Integer> x = new Vector<Number>
需要注意的是限定通配符总是包括自己。
现在我们在方法中自定义泛型,我们实现一个可以交换数组中元素顺序的方法前提是这个数组的类型是未知的
<span style="font-size:14px;"><span style="font-size:14px;">public class HeiMaTest { public static void main(String[] args) throws Exception { swap(new String[]{"黑马程序员","中关村","传智播客"},1,2); } public static <T> T swap(T[] t,int i,int j){ T temp = t[i]; t[i] = t[j]; t[j] = temp; } }<span style="line-height: 20.8800010681152px; font-family: 宋体; background-color: rgb(255, 255, 255);"> </span></span></span>
上面的方法中自定义了一个T的泛型因为是T是新出现的所以的话就在方法的名称前使用<T>对其进行声明
但是如果是在主方法中这样写就是错误的了,swap(new int[]{1,2,3},1,2)因为泛型使用的前提条件是使用的对象如果将int改为Integer的话就可以了。
需要注意的是可以使用泛型变量来表示异常,称为参数化的异常可以用方法中的throws语句中但是不能用于cach语句中。
<span style="font-size:14px;"><span style="font-size:14px;">private static <T extends Exception> void sayHello() throws T{ try { } catch (Exception e) { throw (T)e; } }</span></span>下面我们来看下泛型的综合运用的实例
1.编写一个泛型的方法自动将object类型的对象转换为其他类型
<span style="font-size:14px;"><span style="font-size:14px;">public class HeiMaTest { public static void main(String[] args) throws Exception { String str = convert("黑马"); System.out.println(str); } public static <T> T convert(Object obj){ return (T)obj; } }</span></span>且不说上面的代码是不是有实际意义,主要是要体现一种使用泛型的思想
2.定义一个方法,可以将任意数组中的所有元素填充为相应类型的某个对象
<span style="font-size:14px;"><span style="font-size:14px;">public static <T> void fillArray(T[] t,T obj){ for(int i = 0;i<t.length;i++){ t[i] = obj; } }</span></span>3.采用自定泛型方法的方式打印出任意参数化类型的集合中的所有的内容
<span style="font-size:14px;"><span style="font-size:14px;">public <T> void printArray(Collection<T> c){ for(Object obj:c){ System.out.println(obj); } }</span></span>除了上面的方法我们还可以使用通配符的方式来解决这个问题
<span style="font-size:14px;">public void printArray(Collection<?> c){ for(Object obj:c){ System.out.println(obj); } }</span>但是如果要在打印完之后又有一个需求就是要调用Collection的add方法添加一个元素那么使用泛型就体现出其优越性来了
<span style="font-size:14px;">public <T> void printArray(Collection<T> c,T t){ for(Object obj:c){ System.out.println(obj); } c.add(t); }</span>4.定义一个方法把任意的参数类型的集合中的数据安全的复制到相应类型的另一个数组中
<span style="font-size:14px;">public static <T> void copyArrayToCollection(Collection<T> c,T[] t){ for(int i = 0;i<t.length;i++){ c.add(t[i]); } }</span>定义泛型的类型,在类身上定义泛型
<span style="font-size:14px;">public class StudentDao <T> { public void add(T t){ } public T findById(int id){ return null; } public void update (T t){ } public void delete(T t){ } }</span>上面我们定义了一个操作数据的StudentDao我们只想让他操作Student的数据所以的话我们就在类上定义了泛型。
(6)for each 循环
for(类型 变量名:集合或者是数组)
相关文章推荐
- Maven项目下java.lang.ClassNotFoundException常规解决办法
- Java获取当前的系统时间并格式化输出
- java语言实现顺序表
- Java @override报错的解决方法
- Java-找出两个单链表的首个公共节点
- Myeclipse自带的derby去除
- java中byte与int互转
- java权限设计思路之一
- java中byte与int互转
- java中byte与int互转
- Java泛型 通配符的限定
- java的类加载器ClassLoader
- java自动获得电脑网络配置并存储在beanUtil中
- java的类加载器ClassLoader
- JAVA 中的 Collection FrameWork
- 修改eclipse/MyEclipse中项目包的显示结构
- java集合类都有哪些?主要方法?
- Spring学习笔记之Spring与JDBC整合
- java的类加载器ClassLoader
- java设定窗口步长,依次统计窗口内数值总和