目录
本文讲解的扩展内容,包括:匿名内部类、包装类实现原理分析、装箱与拆箱、数据类型转换。
1、匿名内部类
匿名内部类,故名思意就是没有名字的内部类。匿名内部类有什么用?先看下面的一段简单代码:
【举例】:观察如下代码的问题
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
A a = new X();
a.printA();
}
}
interface A{
public void printA();
}
class X implements A{
@Override
public void printA() {
System.out.println("AAA");
}
}
代码很简单,但是有这样一个问题,程序为接口A定义了一个子类X,但是此时的X子类只用了一次,是否有必要将其单独定义成一个类?设计显着比较冗余,不定义亦可。此时,可以利用匿名内部类解决,匿名内部类必须以抽象类或接口为前提进行使用。
【举例】:使用匿名内部类
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
A a = new A() {
@Override
public void printA() {
System.out.println("AAA");
}
};
a.printA();
}
}
interface A{
public void printA();
}
以上虽然实现了一样的功能,但是基本语法比较糟糕,程序结构也很混乱;目前,可以看懂匿名内部类即可,后续代码经验多了,这种手法自然就熟悉了。
2、包装类实现原理分析
Object类可以接收所有的引用数据类型,因为引用数据类型本质上就是对象,但基本数据类型不是对象,所以Object不能接收基本数据类型。那么将基本数据类型包装一下,就采用如下的代码结构:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Int x = new Int(10);//将基本类型变为包装类
Object obj = x; //对象转型
System.out.println(x.intValue()*x.intValue());
}
}
class Int{
private int num;
public Int(int num) {
this.num = num;
}
public int intValue(){
return this.num;
}
}
以上代码,我们发现,若所有代码都这么设计,存在以下问题:
- Java有8各基本数据类型,需要自己编写这8个基本类型;
- 基本数据类型包装类不能直接参与数学计算;
正因为有这样的需求(参数统一需求),从JDK1.0开始提供了包装类,用户无需自己进行包装类的设计,JDK1.5后,解决了包装类参与数学计算的问题。8中基本数据类型包装类:
byte(Byte)、short(Short)、int(Integer)、long(Long)、float(Float)、double(Double)、char(Character)、boolean(Boolean)。
这8种包装类也分为两种类型:
- 对象型(java.long.Object直接子类):Character、Boolean;
- 数值型(java.lang.Number直接子类):Byte、Short、Integer、Long、Float、Double;
对于Number类,其本质上是一个抽象类:
public abstract class Number extends Object implements Serializable
Number类中有6个操作方法,这6个方法都属于拆箱方法:
- 从包装类取出byte数据:public byte byteValue()
- 从包装类取出int数据:public abstract int intValue()
- 从包装类取出short数据:public short shortValue()
- 从包装类取出long数据:public abstract long longValue()
- 从包装类取出float数据:public abstract float floatValue()
- 从包装类取出double数据:public abstract double doubleValue()
3、装箱与拆箱
基本数据类型与包装类之间的转换存在以下两个概念:
- 装箱操作:将基本数据类型变为包装类;
--Integer类的构造方法:public Integer(int value)
--Double类的构造方法:public Double(double value)
--Boolean类的构造方法:public Boolean(boolean value) - 拆箱操作:将包装类中的基本数据类型取出;
--Number父类中定义的拆箱操作方法:xxxValue()方法
【举例】:以Integer与int为例
Integer x = new Integer(10);
int temp = x.intValue();
【举例】:以Double与double为例
Double y = new Double(1.1);
double temp = y.doubleValue();
所有的装箱与拆箱操作基本都是一个路子,以上方法都是在JDK1.5之前使用的,JDK1.5后提供了自动装箱与拆箱的支持:
Integer x = 100; //自动装箱为类
int y =x;//自动拆箱
System.out.println(++x*10);//自动拆箱进行累加操作
实际上,这种自动装箱的机制,就可以使用Object接收基本数据类型了。
Object obj =10; //转换:10自动装箱为Integer,其向上转型
int temp = (Integer) obj;
System.out.println(obj); //可以正常输出10
System.out.println(temp);
以上的实验,我们可以看出,Object是所有数据类型都可以接收的!!
4、数据类型转换
包装类本身有个非常重要的功能,就是字符串转换为基本数据类型的操作。实际开发中,用户进行数据的输入操作,其类型就是String。
在包装类中提供转换方法,以常用的几个类型为主:
- Integer类方法:public static int parseInt(String s);
- Double类的方法:public static double parseDouble(String s);
- Boolean类的方法:public static boolean parseBoolean(String s);
Character类中没有提供这样的方法,因为String类中有charAt()方法,直接选0索引即可。
【举例】:以Integer为例
String temp = "100";
int num = Integer.parseInt(temp);
System.out.println(num);
但是,实际开发中需要注意,要进行这种转换,字符串必须全部由数字组成,否则会出现NumberFormatException错误;
另外,要注意关于判断比较的问题:
String temp = "100";
int num = Integer.parseInt(temp);
Integer x1=100;
Integer x2=new Integer(100);
System.out.println(x1==num);//true
System.out.println(x1==x2);//false
实际开发中,包装类使用比较多,所以,在进行==比较时,要使用eauals()方法最为保险,和String的情况类似。
【注意】:String要变为基本数据类型,可以使用包装类中的parseXxx()方法,基本数据类型转换为String呢?
- 任何数据类型使用+ 与String连接都会转换为String类型,但是这种方法会产生垃圾;
- 在String中有一组重载的valueOf()方法,可以避免垃圾产生,实际开发中都用这种;
String temp = ""+100; |
String temp = String.valueOf(100); |
5、总结
1)自动装箱与拆箱的特点;
2)Number类的定义及方法;
3)基本数据类型与String的转换;