五、面向对象(下)

1、JAVA增强的包装类

JAVA为8种数据类型定义了相应的引用类型,并称之为基本数据类型的包装类。
(1)自动装箱与自动拆箱
自动装箱就是把一个基本类型变量自动赋值给对应的包装类变量,或者赋值给Object变量;自动拆箱就是将包装类对象直接赋值给一个对应的基本类型变量。
(2)包装类提供了一些方法用于实现基本类型变量和字符串之间的转换
利用包装类提供的parseXxx(String str);静态方法(Character类没有提供该方法)
利用包装类提供的Xxx(String str);构造器
String类也同样提供了多个重载valueOf();方法,用于将基本类型变量转换成字符串。
(3)包装类的比较
包装类和基本类型之间的比较:将两个变量直接进行相比。

Integer a = new Integer();
//输出true
System.out.println("" + (a > 0.5));

包装类与包装类之间的比较:只有两个包装类的实例指向同一个对象的时候才会相等。

Integer a = 2;
Integer b = 2;
System.out.println("" +  (a == b));//返回TRUE
Integer a = 128;
Integer b = 128;
System.out.println("" +  (a == b));//返回FALSE

上面的结论没错!程序也没错!在这里系统将-128~127之间的整数放在了cache的数组中缓存了起来,所以一开始的a和b是指向的同一个对象。而当超过127之后,系统就会重新创建对象,所以后面的a和b就不相等了。

2、处理对象

(1)toString方法
Object类提供的toString方法会返回“类名 + @ + hashcode”值。由于每个类都会直接或者间接继承Object这个类,如果用户不满足Object类中toString方法的返回结果,就应该重写这个方法,来达到自己满意的结果。
(2)==和equals
一般情况下,利用 " == "比较两个引用变量,除非它们指向同一个对象,才会返回TRUE。并且 == 不可用于比较类型上没有父子关系的两个对象。equals方法也是Object的方法,它的功能跟 == 没什么区别,因此我们应当重写equals这个方法,来达到我们预期的目的。

3、final修饰符

(1)什么是final修饰符?
final用于表示它所修饰的类、方法和变量不可改变。
(2)final修饰变量
<1>因为一旦经过final进行过修饰便不能被改变。因此对于成员变量来说赋初值要遵循以下原则。
类变量:必须在静态初始化快中指定初始值或者声明该类变量时指定初始值
实例变量:必须在非静态初始化块、声明该变量实例或者构造器中指定初始值
<2>final也可以修饰局部变量,当定义final局部变量的时候没有赋初始值,那么可以在接下来对进行一次赋值,只能一次。如果在定义的时候已经指定了的话,那么在以后就不可以再对该变量赋值。
(3)final修饰方法
final修饰的方法不可以被重写,但是依然可以被重载。
(4)final修饰类
final修饰的类不可以有子类。
(5)不可变类
不可变类指的是创建该类的实例之后,该实例的实例变量是不可改变的。

4、抽象类

(1)什么是抽象类?
有抽象方法的类或者使用abstract修饰符修饰的类。
(2)抽象方法和抽象类的定义规则
<1>抽象类和抽象方法必须使用abstract修饰符来修饰。抽象方法不能有方法体。
<2>抽象类不能被实例化。
<3>含有抽象方法的类只能被定义成抽象类。
注:abstract不能用于修饰局部变量,也就是说没有抽象变量,抽象成员变量的说法。也不能用于修饰构造器。
如果用static修饰方法,那么这个方法是类方法,可以被调用。但如果同时加上abstract来进行修饰,则会导致调用该方法时发生冲突,因此两个修饰符不能同时使用。
子类中含有没有重写的abstract方法,那么子类依然是一个抽象类。因此abstract不能和private同时使用。

5、接口

(1)什么是接口?
特殊的抽象类,是多个类共同的公共行为规范。
(2)接口的定义

[修饰符] interface 接口名 extends 父接口1, 父接口2...
{
	//常量定义
	.....
	//抽象方法定义
	.....
	//内部类、接口、枚举定义...
	.....
	//默认方法或者类方法定义
	......
}

注:接口的成员变量只能是静态常量,因此在定义成员变量的时候不管是否使用public static final修饰符来修饰,接口的成员变量总是使用这三个修饰符来修饰。接口的方法只能是抽象方法、类方法、或者默认方法,抽象方法默认使用abstract来修饰,默认方法必须使用default来修饰,由接口实现类的实例来调用这些默认方法,类方法必须使用static来修饰,可以直接使用接口来调用。
(3)接口的继承
接口支持多继承。即一个接口可以有多个直接父接口。子接口会获得父接口里定义的所有抽象方法和常量。
(4)接口的用途
定义变量:用于进行强制类型转换,即为接口变量赋值的时候必须使用其实现类的对象。也就是说,哪个类实现了这个接口,那么这个类的对象就可以为这个接口的变量赋值。
调用接口中定义的常量
被其他类实现:一旦类实现了一个或者多个接口,那么这个类必须实现这些接口里定义的全部抽象方法,否则该类会成为抽象类。

6、内部类

1、内部类的定义和作用。
定义:把一个类放在另一个类的内部进行定义。
作用:<1>、可以实现更好的封装,不允许同一个包中的其他类访问该类。
<2>、内部类可以访问外部类的私有数据,但外部类不可以访问内部类成员。
<3>、匿名内部类仅适合创建那些仅需要一次使用的类。
<4>、内部类可以多使用private,protected,static修饰符。
<5>、非静态内部类不可以拥有静态成员。
2、非静态内部类
没有使用static修饰的内部类是非静态内部类。
不论是外部类的类成员变量,还是实例成员变量都不能访问非静态内部类的成员。
3、静态内部类
使用static修饰的内部类是静态内部类。
静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。
外部类依然不能直接访问静态内部类的成员,但可以用静态内部类的类名作为调用者来访问静态内部类的类成员,使用静态内部类的类对象来访问静态内部类的实例成员。
接口中也可以定义内部类,但接口里定义的内部类默认使用public static修饰,即接口内部类只能是静态内部类。
4、使用内部类
<1>在外部类以外的地方定义内部类,语法格式:

Outerclass.Innerclass varName = new Outerclass.Innerclass();//静态内部类
Outerclass.Innerclass varName = new Outerclass().new Innerclass();//非静态内部类

5、匿名内部类
<1>匿名内部类的特点
创建匿名内部类的时候会立即创建出一个该类的对象,这个类定义立即消失,匿名内部类不能重复使用。
<2>语法格式

new 实现接口() | 父类构造器(实参列表)
{
	//匿名内部类的类体
}

<3>匿名内部类的规则
匿名内部类必须继承一个父类或者实现一个接口,但最多只能继承一个父类或者实现一个接口;
匿名内部类不能是抽象类,也就是说必须将父类或者接口中的抽象方法全部实现;
匿名内部类不能定义构造器,因为匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以定义初始化块,通过初始化块来完成构造器需要完成的事情;
匿名内部类的使用的局部变量是一个final变量。

7、Lambda表达式

<1>组成部分
形参列表:形参列表允许省略形参类型。如果形参列表中只有一个参数,甚至连形参列表的圆括号也可以省略;
箭头(->);
代码块:如果代码块中只包含一条语句,那么可以省略花括号;Lambda代码块中只有一条return语句,可以省略return关键字。

fun(array, (int[] target)->{
	System.out.println("哈哈!");//可以省略花括号
});

<2>Lambda表达式使用要求
必须是函数式接口,也就是说该接口只能有一个抽象方法。Lambda只能为函数式接口创建对象。
<3>Lambda表达式的用途
将Lambda表达式赋值给函数式接口类型的变量;
将Lambda表达式作为函数式接口类型的参数传给某个方法;
使用函数式接口对Lambda表达式进行强制转换。

//最后一个用途示例
//按理说Object不是函数式接口,但可以通过强转进行赋值
Object obj = (Runnable)()->3;

<4>方法引用和构造器引用
如果Lambda表达式只有一句代码,那么可以在代码块中使用方法和构造器引用。

种类 示例 Lambda表达式
引用类方法 类名::类方法 (a,b,…)->类名.类方法(a,b,…)
引用特定对象的实例方法 特定对象::实例方法 (a,b,…)->特定对象.实例方法(a,b,…)
引用某类对象的实例方法 类名::实例方法 (a,b,…)->a.实例方法(a,b,…)
引用构造器 类名::new (a,b,…)->new 类名(a,b,…)

8、枚举类

<1>枚举类与普通类的区别
枚举类可以实现一个或者多个接口,使用enum定义的枚举类默认继承了java.lang.Enum类,而不是Object类,因此枚举类不能显式继承其他父类;
非抽象的枚举类默认使用final修饰,因此枚举类不可派生出子类;
枚举类的构造器只能使用private访问控制符;
枚举类的所有实例必须在枚举类的第一行显式列出,否则枚举类永远不能产生实例。枚举类的实例系统默认自动添加public static final修饰符。
<2>实现接口的枚举类
如果需要每个枚举值在调用该方法的时候呈现出不同的行为方式,则可以让每个枚举值分别实现该方法,每个枚举值提供不同的实现方法。
<3>包含抽象方法的枚举类
枚举类中定义抽象方法时不能使用abstract关键字将枚举类定义成抽象类,系统会自动添加,但因为枚举类需要显式创建枚举值,而不是作为父类,所以定义每个枚举值时必须为抽象方法提供实现,否则将出现编译错误。

猜你喜欢

转载自blog.csdn.net/qq_35381323/article/details/85240171
今日推荐