目录
多态
引用类型转换
内部类
成员内部类
匿名内部类(重点)
引用类型使用小结
包装类
多态
概述:
- 多态是面向对象三大特征之一。
- 多态指对于同一行为,对于不同的对象,具有不同的表现形式。在程序中,表示对同一方法,不同的对象有不同实现。
- 实现多态的前提条件
- 继承或者实现
- 父类引用指向子类对象或接口的引用指向实现类的对象
- 方法的重写(没有重写方法多态是没有意义的)
实现多态:
-
父类的引用指向子类的对象:
- 格式: 父类类型 变量名 = new 子类类型(实参);
- eg: Fu f = new Zi();
-
接口的引用指向实现类的对象:
- 格式: 接口名 变量名 = new 实现类名(实参);
- eg: IA a = new Imp();
扩展:
- 向上转型: 父类类型的引用指向子类类型的对象
- 向下转型: 子类类型向父类类型转换的过程
多态时访问成员的特点:
- 1.成员变量: 编译看左边(父类),运行看左边(父类)
- 2.成员方法:
- 非静态成员方法:编译看左边(父类),运行看右边(子类)
- 静态成员方法: 编译看左边(父类),运行看左边(父类)
- 记忆: 除了非静态成员方法编译看左边,运行看右边,其余都看左边
多态的几种表现形式:
-
普通父类多态
public class Fu{} public class Zi extends Fu{} public class Test{ public static void main(String[] args){ Fu f = new Zi();// 多态 } } -
抽象父类多态
public abstract class Fu{} public class Zi extends Fu{} public class Test{ public static void main(String[] args){ Fu f = new Zi();// 多态 } } -
父接口多态
public interface IA{} public class Imp implements IA{} public class Test{ public static void main(String[] args){ IA a = new Imp();// 多态 } }
多态的应用场景:
-
变量多态 -----> 意义不大
-
形参多态----> 常用
-
参数的类型是父类类型,那么就可以接收该父类类型的对象以及该父类类型的所有子类对象
-
-
返回值多态---> 常用
- 返回值类型为父类类型,那么就可以返回该父类类型的对象,或者该父类类型的子类对象
多态的好处和弊端:
-
好处:
- 可以将方法的参数定义为父类引用,使程序编写的更简单,提高程序的灵活性,扩展性
- 案例参考多态的应用场景
-
弊端:
-
无法直接访问子类独有的成员变量和成员方法(因为多态时成员访问特点编译都是看左边(父类))
-
引用类型转换
-
为什么要转型:
- 为了实现多态
- 为了解决多态的弊端(无法访问子类独有的成员变量和成员方法)
-
如何转型:
- 向上转型:子类类型向父类类型转换的过程,称为向上转型。这个过程是默认的。
- 格式:父类类型 变量名 = new 子类类型() 或 子类对象引用;
Dog d = new Dog();
Animal anl = new Dog();
Animal anl = d;
- 向下转型:父类类型向子类类型转换的过程,称为向下转型,这个过程需要强制执行。
- 格式:子类类型 变量名 = (子类类型) 父类类型变量;
- 注意: 父类类型的变量指向的对象一定是左边子类类型的对象,否则会报类型转换异常ClassCastException
-
避免转型异常--->转型判断:
- instanceof关键字
- 格式: 变量名 instanceof 数据类型
- 原因:父类类型的变量指向的对象不是左边子类类型 或 不存在子父类关系
- 执行:
- 如果变量指向的对象的数据类型是属于后面的数据类型,就返回true,否则返回false
为什么要转型:
- 为了实现多态
- 为了解决多态的弊端(无法访问子类独有的成员变量和成员方法)
如何转型:
- 格式:父类类型 变量名 = new 子类类型() 或 子类对象引用;
Dog d = new Dog(); Animal anl = new Dog(); Animal anl = d;
- 格式:子类类型 变量名 = (子类类型) 父类类型变量;
- 注意: 父类类型的变量指向的对象一定是左边子类类型的对象,否则会报类型转换异常ClassCastException
避免转型异常--->转型判断:
- instanceof关键字
- 格式: 变量名 instanceof 数据类型
- 原因:父类类型的变量指向的对象不是左边子类类型 或 不存在子父类关系
- 执行:
- 如果变量指向的对象的数据类型是属于后面的数据类型,就返回true,否则返回false
内部类
内部类的概述:
- 概述: 将一个类定义在另一个类的里面,里面的那个类就叫做内部类,外面的那个类就叫做外部类
- 特点: 内部类是一个独立的类,在编译后,有自己独立的class文件,前面冠以:外部类名+$+内部类类名
- 分类:
- 成员内部类
- 匿名内部类
- 局部内部类(自己了解)
成员内部类
-
概述: 定义在类的成员位置(类中方法外)的类就叫做成员内部类
-
格式:
class 外部类名{
class 内部类名{
}
}
-
成员访问特点:
-
成员内部类中的成员变量和成员方法在其他类中访问,需要创建成员内部类对象
-
格式: 外部类名.内部类名 对象名 = new 外部类名().new 内部类名();
- 注意事项:
-
在成员内部类中,可以直接访问外部类的一切成员,包括外部类的私有成员
-
在外部类中,需要直接访问内部类的成员,需要创建内部类对象来访问
匿名内部类(重点)
-
概述
- 本质其实就是一个类的子类对象
- 本质其实就是一个接口的实现类对象
-
格式
new 类名(){
必须重写所有抽象方法
};
new 接口名(){
必须重写所有抽象方法
};
-
使用场景
- 如果想得到一个抽象类的子类对象,那么就可以直接给该类的匿名内部类
- 如果想得到一个接口的实现类对象,那么就可以直接给该接口的匿名内部类
引用类型使用小结
概述: 定义在类的成员位置(类中方法外)的类就叫做成员内部类
格式:
class 外部类名{
class 内部类名{
}
}
成员访问特点:
-
成员内部类中的成员变量和成员方法在其他类中访问,需要创建成员内部类对象
-
格式: 外部类名.内部类名 对象名 = new 外部类名().new 内部类名();
-
在成员内部类中,可以直接访问外部类的一切成员,包括外部类的私有成员
-
在外部类中,需要直接访问内部类的成员,需要创建内部类对象来访问
-
概述
- 本质其实就是一个类的子类对象
- 本质其实就是一个接口的实现类对象
-
格式
new 类名(){ 必须重写所有抽象方法 }; new 接口名(){ 必须重写所有抽象方法 }; -
使用场景
- 如果想得到一个抽象类的子类对象,那么就可以直接给该类的匿名内部类
- 如果想得到一个接口的实现类对象,那么就可以直接给该接口的匿名内部类
引用类型使用小结
引用类型作为方法参数和返回值:
- 引用类型作为方法的参数传递的是地址值
- 引用类型作为方法的返回值返回的是地址值
引用类型作为成员变量:
- 成员变量类型为抽象类,那么就赋该抽象类的子类对象
- 成员变量类型为接口,那么就赋该接口的实现类对象
引用类型的使用:
- 引用类型作为方法的参数类型和返回值类型
- 参数的类型为接口类型,调用的时候就得传入该接口的实现类对象
- 参数的类型为类类型,调用的时候就可以传入该类的对象或者其子类对象
- 返回值类型为接口类型,方法体就只能返回该接口的实现类对象
- 返回值类型为类类型,方法体就可以返回该类的对象或者其子类对象
- 引用类型作为参数传递,传递的是地址值,形参发生改变会影响实参
包装类
包装类的概述:
-
概述: 为了更好的维护基本类型数据,java为基本类型创建了对应的引用类型,这些类称为包装类
-
分类:
| 基本类型 | 对应的包装类(位于java.lang包中) | | byte | Byte | | short | Short | | int | Integer | | long | Long | | float | Float | | double | Double | | char | Character | | boolean | Boolean |
Integer类的使用:
-
概述: int类型对应包装类,包装一个对象中的原始类型 int 的值
-
构造方法
- public Integer(int value) 根据 int 值创建 Integer 对象(过时)
- public Integer(String s) 根据 String 值创建 Integer 对象(过时)
-
静态方法
- public static Integer valueOf(int i) 返回表示指定的 int 值的 Integer 实例
- public static Integer valueOf(String s) 返回保存指定String值的 Integer 对象
-
public int intValue() 以 int 类型返回该 Integer 的值
-
代码:
public class Test { public static void main(String[] args) { // Integer的构造方法 Integer i1 = new Integer(10);// 表示整数10 Integer i2 = new Integer("10");// 表示整数10 // Integer的静态方法 Integer i3 = Integer.valueOf(10);// 表示整数10 Integer i4 = Integer.valueOf("10");// 表示整数10 } } -
拆箱和装箱
-
装箱: 把基本类型转换为对应的包装类类型---->包装类的构造方法valueOf静态方法可以实现
byte--->Byte short-->Short int---->Integer long--->Long float-->Float double->Double boolean->Boolean char---->Character
-
-
拆箱: 把包装类类型转换为对应的基本类型---->包装类的 xx类型Value() 非静态方法实现
Byte-->byte Short->short Integer->int Long--->long Float-->float Double-->double Boolean-->boolean Character->char
自动装箱和自动拆箱:
-
自动装箱: 基本类型自动转换为对应的包装类类型---->直接把基本类型的值赋值给对应的包装类类型变量
-
Integer i = 100;
-
Character c = 'a';
-
-
自动拆箱: 包装类类型自动转换为对应的基本类型---->直接把包装类的对象赋值给对应的基本类型的变量
int num = i; char ch = c; System.out.println("i = " + i);// 100 System.out.println("num = " + num);// 100 System.out.println("c = " + c);// 'a' System.out.println("ch = " + ch);// 'a'
基本类型与字符串之间的转换:
-
基本类型-->字符串:
-
方式一:直接使用基本类型的数据加上一个空字符串 `数据+""
-
String str1 = 100 + ""; // "100"
-
-
方式二: 通过String类静态方法public static String valueOf(基本类型的值);
-
String str2 = String.valueOf(100);
-
System.out.println("str1 = " + str1); // "100"
-
-
- 字符串-->基本类型:
-
方式一: 通过包装类的静态方法valueOf(String s)得到包装类对象,然后包装类对象自动拆箱为基本类型--->除了Character包装类之外,所有包装类都有这个方法
// 返回的是Integer对象,但会自动拆箱为int值,所以可以使用int类型的变量接收 int i = Integer.valueOf("100"); System.out.println("i = " + i); // 100// 返回的是Boolean对象,但会自动拆箱为boolean值,所以可以使用boolean类型的变量接收 boolean b = Boolean.valueOf("false"); System.out.println("b = " + b);// false - 方式二: 通过包装类的静态方法parseXXX类型(String s)得到对应的基本类型--->除了Character包装类之外,所有包装类都有这个方法
int num = Integer.parseInt("100"); System.out.println("num = " + num);// 100 boolean res = Boolean.parseBoolean("true"); System.out.println("res = " + res);// true -



