内部类、自动拆装箱

内部类

概念: 定义在类中的类
内部类可以是静态static的,也可用public,default,protected和private修饰。

划分: 成员内部类、局部内部类、匿名内部类

为什么要用内部类: 类的生命周期程序运行时开始到程序结束时销毁,但是呢,某些情况下,在整个应用程序中对该类的使用频率较低,那此时就需要将其定义为内部类,以缩短其生命周期。

使用场景: 当类或该类的对象并不是很常用的时候,就可以定义为内部类

成员内部类

成员内部类,就是作为外部类的成员,可以直接使用外部类的所有成员和方法,即使是private的。同时外部类要访问内部类的所有成员变量/方法,则需要通过内部类的对象来获取。

要注意的是,成员内部类不能含有static的变量和方法。因为成员内部类需要先创建了外部类,才能创建它自己的,了解这一点,就可以明白更多事情,在此省略更多的细节了。

在成员内部类要引用外部类对象时,使用outer.this来表示外部类对象;

而需要创建内部类对象,可以使用outer.inner obj = outerobj.new inner();

class Outer{
	private int id = 10;
	public void out(){
		System.out.println("这是外部类的方法");
	}
	
	// 注: 这个public不能省略
	// 注: 内部类可以加上static 修饰, 就叫静态内部类, 缺点是无法直接调用非静态的属性值;
	public class Inner{
		public void in(){
			System.out.println("这是内部类的方法");
		}
		
		// 获得外部类的私有属性~
		public void getID(){
			System.out.println(id);
		}
	}
}

public class Application{
	public static void main(String[] args){
		Outer outer = new Outer();
		// 通过这个外部类来实例化内部类~
		outer.Inner() inner = outer.new Inner();
		inner.in();
		inner.getID();
	}
}

局部内部类

局部内部类,是指内部类定义在方法和作用域内。

class Outer{
	// 局部内部类
	public void method(){
		class Inner{
			public void in(){
			}
		}
	}
}

public class Application {
	public static void main(String[] args){
		Outer outer = new Outer();
	}
}

局部内部类也像别的类一样进行编译,但只是作用域不同而已,只在该方法或条件的作用域内才能使用,退出这些作用域后无法引用的。

匿名内部类

没有类名的局部内部类(一切特征都与局部内部类相同)
必须继承一个父类或者实现一个接口
定义类、实现类、创建对象的语法合并,只能创建一个该类的对象(类信息只用到一次)
减少代码量,书写思路流程。

public class TestInnerLocalForApply {
	public static void main(String[] args) {
		//学校开设新班
		/*1.
		Teacher teacher = new AdvancedTeacher();//家长提出意见需要高级教师
		teacher.teach();//问题就是校方没办法提供如此多的高级教师
		 */
		//校方出台了内部规则(按照班级的奇偶编号进行均匀分派,奇数初级,偶数高级)
		
		Teacher t =School.getTeacher(1);
		t.teach();
		Teacher t1 =School.getTeacher(2);
		t1.teach();
		
	}
}
class School{
	public static Teacher getTeacher(int classNo) {//使用静态方法,无需new School
		Teacher currentTeacher = null;
		
		
		if(classNo%2 !=0) {
			currentTeacher = new Teacher() {
				@Override
				public void teach() {
					System.out.println("初级老师在上课");
				}
			};
		}else {
			currentTeacher = new Teacher() {
				@Override
				public void teach() {
					System.out.println("高级老师在上课");
				}
			};
		}
		return currentTeacher;
	}
}

abstract class Teacher{
	public abstract void teach();
}

自动拆装箱

自动装箱和拆箱,就是基本类型和引用类型的相互转换。

包装类型

Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的,这在实际使用时存在很多的不便,为了解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类(Wrapper Class)。

包装类均位于java.lang包,包装类和基本数据类型的对应关系如下表所示

基本数据类型包装类
shortShort
charCharacter
intInteger
longLong
floatFloat
doubleDouble
booleanBoolean

在这八个类名中,除了Integer和Character类以后,其它六个类的类名和基本数据类型一致,只是类名的第一个字母大写即可。

为什么需要包装类

很多人会有疑问,既然Java中为了提高效率,提供了八种基本数据类型,为什么还要提供包装类呢?

这个问题,其实前面已经有了答案,因为Java是一种面向对象语言,很多地方都需要使用对象而不是基本数据类型。比如,在集合类中,我们是无法将int 、double等类型放进去的。因为集合的容器要求元素是Object类型。

为了让基本类型也具有对象的特征,就出现了包装类型,它相当于将基本类型“包装起来”,使得它具有了对象的性质,并且为其添加了属性和方法,丰富了基本类型的操作。

自动拆箱与自动装箱

在Java SE5中,为了减少开发人员的工作,Java提供了自动拆箱与自动装箱功能。

自动装箱: 就是将基本数据类型自动转换成对应的包装类。

自动拆箱:就是将包装类自动转换成对应的基本数据类型。

//手动装箱
int i=1;
Integer a=new Integer(i);
//自动装箱
Integer b=1;
Integer j=new Integer(8);
//手动拆箱
int m=j.intValue();
//自动拆箱
int n=j;

一些例子

public static void main(String[] args) {        

        Integer a=new Integer(123);
        Integer b=new Integer(123);
        System.out.println(a==b);//输出 false

        Integer c=123;
        Integer d=123;  
        System.out.println(c==d);//输出 true

        Integer e=129;
        Integer f=129;
        System.out.println(e==f);//输出 false

        int g=59;
        Integer h=new Integer(59);
        System.out.println(g==h);//输出 true
    }

代码1好理解,因为新建了不同的对象。
代码2为什么返回true呢?原来自动装箱的源码简化如下:

public static Integer valueOf(int i) {       
        if (i >= -128 && i <= 127)
            return IntegerCache.cache[i + 127];
            //如果i的值大于-128小于127则返回一个缓冲区中的一个Integer对象
        return new Integer(i);
        //否则返回 new 一个Integer 对象
    }

IntegerCache 类在初始化的时候,生成了一个大小为 256 的integer 类型的常量池,并且integer.val 的值从-128-127,当我们运行 Integer c=a ;时,如果 -128<=a<=127时,不会再生成新的integer对象,直接从常量池中找到对应的已经初始化后的对象。当 a<-128||a>127时才会生成一个新的对象。所以代码3返回的也是false
值得注意的是代码4中,最后在比较g h 的值时,用了自动拆箱,g == h 这一代码执行的是:g==h.IntValue(),而h.IntValue()= 59 。所以实际上比较的是两个int类型,返回为true。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值