1.ClassCastException异常和Object类的转型
ClassCastException:数据类型转换错误
ClassCastException是数据类型转换错误,比如有个 String temp=“abc”; 你 (int)temp就会报错了,以为他们类型不一样,但是你(object)temp就行,因为object是他们的父类。
Object类转型:
整型数据:基本数据类型 -> 包装为Integer类对象 ->自动向上转型为Object;
浮点型数据:基本数据类型 -> 包装为Double类对象 ->自动向上转型为Object;
字符串型数据:String 类对象 -> 自动向上转型为Object;
2.泛型
如果想要避免项目之中出现"ClassCastException"最好的做法是可以直接回避掉对象的强制转换,所以在JDK1.5之后提供有泛型的技术,而泛型的本质在于,类中的属性或方法的参数与返回值的类型可以由对象实例化的时候动态决定。那么此时就需要在类定义的时候明确的定义占位符(泛型标记)。
例如:定义一个Point类
class Point <T>{
private T x;
private T y;
public void setX(T x){
this.x=x;
}
public void setY(T y){
this.y=y;
}
public T getX(){
return this.x;
}
public T getY(){
return this.y;
}
}
public class test {
public static void main(String[] args) {
Point point = new Point();
point.setX(10);
point.setY(20);
int x = (Integer) point.getX();
int y = (Integer) point.getY();
System.out.println("x坐标: " + x + ",y坐标:" + y);
}
}
这里Point类中的x与y属性的数据类型并不确定,而是由外部来决定。
提示一下:关于默认的泛型类型
由于泛型是属于JDK1.5之后的产物,但是在这之前已经有不少内置的程序类或者是接口已经广泛的应用在项目开发之中,于是为了保证这些类或接口追加了泛型之后,原始的程序类依然可以使用,所以如果不设置泛型类型时,自动将Object作为类型,以保证程序的正常执行,但是在编译的过程之中会出现警告信息。
例如:
class Point<T> {
private T x;
private T y;
public void setX(T x) {
this.x = x;
}
public void setY(T y) {
this.y = y;
}
public T getX() {
return this.x;
}
public T getY() {
return this.y;
}
}
public class test {
public static void main(String[] args) {
Point<Integer> point = new Point<Integer>();
point.setX(10);
point.setY(20);
int x = point.getX();
int y = point.getY();
System.out.println("x坐标: " + x + ",y坐标:" + y);
}
}
现在的程序代码之中,由于Point类设置的泛型类型为Integer,这样所有的对应此泛型的属性、变量、方法返回值,就将全部替换为Integer,但只局限于此对象当中。
泛型的使用注意点:
1.泛型之中只允许设置引用类型,如果现在要操作基本类型必须使用包装类;
例如:将Integer换成int就不可以执行了。
2.从JDK1.7开始,泛型对象实例化可以简化为:
"Point<Integer> point = new point();"后面<>可以省略!!
3.泛型通配符
虽然泛型帮助开发者解决了一系列的对象的强制转换所带来的安全隐患,但是从另外一个角度来讲,泛型也带来了一些新的问题:引用传递处理
例如:
class Message<T>{
private T content;
public void setContent(T content){
this.content = content;
}
public T getContent(T content){
return this.content;
}
}
public class test {
public static void main(String[] args) {
Message<String> msg = new Message<String>();
msg.setContent("WWW.BAIDU.COM");
fun(msg);
}
public static void fun(Message<String> tmp){
System.out.println(tmp.getContent());
}
}
这里问题的关键在于fun()的函数引用,如果真的去使用泛型不可能只是一种类型,也就是说fun()方法按理应该可以接受任意种泛型类型的Message对象。
如果这里函数引用不设置泛型:
例如:
class Message<T>{
private T content;
public void setContent(T content){
this.content = content;
}
public T getContent(T content){
return this.content;
}
}
public class test {
public static void main(String[] args) {
Message<Integer> msg1 = new Message<Integer>();
Message<String> msg2 = new Message<String>();
msg1.setContent(110);
fun(msg1);//引用传递
msg2.setContent("www.baidu.com");
fun(msg2);
}
public static void fun(Message tmp){
tmp.setContent(1.1);
System.out.println(tmp.getContent());
}
}
这里的fun函数没有设置泛型,反而出现了更大的问题,在函数里面写入tmp.setContent(1.1);发现上面的结果全都变成了1.1。
这个时候发现如果不设置泛型,那么在方法之中就有可能对你的数据进行修改,所以此时需要找一种方案:可以接受所有的泛型类型,并且不能够修改里面的数据(但是允许获取),那么就需要通配符"?"来解决。
例如:
class Message<T> {
private T content;
public void setContent(T content) {
this.content = content;
}
public T getContent(T content) {
return this.content;
}
}
public class test {
public static void main(String[] args) {
Message<Integer> msg1 = new Message<Integer>();
Message<String> msg2 = new Message<String>();
msg1.setContent(110);
fun(msg1);//引用传递
msg2.setContent("www.baidu.com");
fun(msg2);
}
public static void fun(Message<?> tmp) {
System.out.println(tmp.getContent());
}
}
此时在fun()方法里面由于采用了Message结合统配符的处理所以可以接受所有的类型,并且不允许修改,只允许获取数据。
提示一下:
" ? "在通配符的基础上还有两个类型的通配符:
1." ? extends 类 " :设置泛型的上限
例如:
" ? extends Number "表示该泛型类型只允许设置Number或Number的子类。
2. " ? super 类 " :设置泛型的下限
例如:
" ? super String " 表示只能够使用String或其父类。
3.泛型接口
泛型除了可以在类上定义之外也可以直接在接口之中进行使用。
实现方式一:在子类之中继续设置泛型定义
例如:
interface IMessage<T> {
public String echo(T t);
}
class MessageImpl<S> implements IMessage<S> {
public String echo(S t) {
return "ECHO " + t;
}
}
public class test {
public static void main(String[] args) {
IMessage<String> msg = new MessageImpl<String>();
System.out.println(msg.echo("www.baidu.com"));
}
}
实现方式二:在子类实现父接口的时候直接定义出具体泛型类型
interface IMessage<T> {
public String echo(T t);
}
class MessageImpl implements IMessage<String> {
public String echo(String t) {
return "ECHO " + t;
}
}
public class test {
public static void main(String[] args) {
IMessage<String> msg = new MessageImpl();
System.out.println(msg.echo("www.baidu.com"));
}
}
两种实现方式原则,一定要熟练!!!
4.泛型方法
在之前的程序类里面实际上已经可以发现在泛型类之中如果将泛型标记写在了方法上,那么这样的方法就被称为泛型方法,但是需要注意的是,泛型方法不一定非要出现在泛型类之中,即:如果一个类上没有定义泛型,也可以使用泛型方法。
例如:
public class test {
public static void main(String[] args) {
Integer num[] = fun(1, 2, 3);
for (int temp : num)
System.out.print(temp + ",");
}
//这种的泛型方法,非常常见!
public static <T> T[] fun(T... args) {
return args;
}
}
这种泛型方法是非常常见的!!!!