1.多态
1.1多态的概念
-
概念
一个对象可以表现多种形态,这就叫做是多态。
比如:我们可以说猫是一只猫,我们也可以说猫是一个动物
-
java中多态的前提
- 要有继承extends或者实现implements关系
- 体现多态要有方法重写
- 要有父类引用指向子类对象
-
示例代码
//创建对象 Cat c = new Cat(); //要有父类引用指向子类对象 Animal a = new Cat();
1.2多态的成员访问特点
-
成员变量
编译看左边(父类),运行看左边(父类)
-
成员方法
编译看左边(父类), 运行看右边(子类)
-
代码演示
//动物 public class Animal { String name = "王健林"; public void method(){ System.out.println("父类的方法"); } } //猫 public class Cat extends Animal{ String name = "王思聪"; public void method(){ System.out.println("子类的方法"); } } public class Demo { public static void main(String[] args) { //创建对象 Cat c = new Cat(); //要有父类引用指向子类对象 Animal a = new Cat(); //编译看左边(父类),运行看左边(父类) System.out.println(a.name); //编译看左边(父类), 运行看右边(子类) a.method(); } }
1.3多态的好处和弊端
-
弊端
多态情况下,不能调用子类的特有方法
//要有父类引用指向子类对象 Animal a = new Cat(); //不能调用子类的特有内容 a.catchMouse();
-
好处
提高了代码的扩展性
public class Demo多态的好处 { public static void main(String[] args) { //调用方法 method(new Cat()); method(new Dog()); } //不使用多态,需要定义无数个方法。。。。。。 /* //接受猫类型 public static void method(Cat c){ //相当于 Cat c = new Cat(); } //接口狗类型 public static void method(Dog d){ //相当于 Dog d = new Dog(); } */ //使用多态 //一个方法可以接受任意动物的子类,这个方法提高了代码扩展性 public static void method(Animal a){ //相当于 Animal a = new Cat(); // Aniaml a = new Dog(); } }
1.4接口体现多态的案例
-
笔记本案例要求:
定义USB接口,接口中定义yong()方法
定义Computer电脑类,类中定义使用USB设备的方法use(USB usb)
定义Mouse鼠标类,类中实现USB接口,供电脑使用
定义KeyBoard键盘类,类中实现USB接口,供电脑使用
定义测试类进行测试电脑的方法
-
示例代码
1.5多态的转型
-
向上转型
把子类类型转成父类类型
Animal a = new Cat(); //把Cat类型转成Animal类型
-
向下转型
把父类类型转成子类类型
//子类类型 变量名 = (子类类型)父类类型对象; Cat c = (Cat) a; 作用: 为了调用子类的特有方法
-
类型转化异常
ClassCastException类型转换异常 做了不正确的向下转型时会出现这个异常
-
关键字instanceof
-
作用
instanceof可以判断一个对象是否是某种类型,可以避免出现类型转换异常
-
格式
对象 instanceof 类型 如果这个对象是后面这种类型就会返回true 如果这个对象不是后面这种类型就会返回false 我们就可以使用这个关键字对对象进行判断
-
示例代码
public class Demo转型问题的解决 { public static void main(String[] args) { //小王写的: Animal a = new Cat(); //--------------------------------------- //老王写的: //小王告诉老王a动物是一个猫 //老王在转换之前先做判断 if(a instanceof Cat){ //向下转型 Cat c = (Cat)a; c.catchMouse(); } //作用:避免类型转换异常的发生!!! } }
-
2.内部类
2.1内部类的概念
-
概念:
内部类就是定义类类里面的类,比如每个人都有心脏。人是一个类,心脏也是一个类,心脏就是人的内部类。
-
分类:
- 成员内部类
- 局部内部类
- 匿名内部类
2.2成员内部类
-
概念:
定义在类中方法外的内部类就是成员内部类
-
在测试类中创建对象的方式:
外部类名.内部类名 变量名 = new 外部类().new 内部类();
-
变量重名时的访问:
访问外部类的成员变量: 外部类名.this.变量名
-
示例代码:
//外部类
//外部类
public class AAA {
//外部类的成员变量
String name = "周星驰";
//成员内部类
class BBB{
//内部类的成员变量
String name = "大鹏";
//BBB的方法
public void method(){
//局部变量
String name = "柳岩";
System.out.println(name); //柳岩 就近原则
System.out.println(this.name); //大鹏 this用来区分局部变量和成员变量的重名
System.out.println(AAA.this.name); //周星驰
}
}
}
//测试类
public class Demo成员内部类测试 {
public static void main(String[] args) {
//创建对象
AAA a = new AAA();
//创建内部类对象
//外部类名.内部类名 变量名 = new 外部类().new 内部类();
AAA.BBB b = new AAA().new BBB();
//调用内部类方法
b.method();
}
}
2.3局部内部类
-
概念:
定义在方法中的内部类就叫做是局部内部类
//外部类 public class CCC { //定义方法 public void method(){ //外部类的局部变量 int a = 10; //局部内部类 class DDD{ //内部类的方法 public void show(){ System.out.println("内部类的方法"); } } } }
-
作用:
局部内部类没什么大作用,因为局部限制了他的使用范围,只能在当前方法中使用,所以这个东西真没什么使用场景。
-
局部内部类的小问题:
- 在局部内部类中访问了外部类的局部变量,那么这个变量就变成了final变量,不能被修改。
//外部类 public class CCC { //定义方法 public void method(){ //外部类的局部变量 //如果在局部内部类中访问了外部类的局部变量,那么这个变量会自动被final修饰 int a = 10; //局部内部类 class DDD{ //内部类的方法 public void show(){ System.out.println(a); //修改a的值 //被final修饰的变量不能修改 a = 20; } } } }
2.4匿名内部类
-
概念
没有类名的内部类就是匿名内部类
-
格式
new 类名/接口名(){ 方法重写 };
-
代码演示
//写法一: //这个代表Animal的子类对象,子类叫啥??没有类名 Animal a = new Animal(){ @Override public void eat() { System.out.println("匿名内部类吃饭方法"); } }; //写法二: //调用方法 method(new Animal(){ @Override public void eat() { System.out.println("匿名内部类吃饭方法"); } });
-
本质
匿名内部类的本质其实是类或接口的子类对象。
-
匿名内部类作用
作用是简化代码。之前需要单独定义一个类,现在不用单独定义类。
匿名内部类可用可不用。对于初学者来说因为格式复杂阅读性低所以不习惯用,但是在工作中经常使用匿名内部类。因为对代码熟悉了之后,觉得代码写的越简单越好。
2.5内部类小结
成员内部类【我们不写,java源码中可以看到】
局部内部类【我们不写java中也很少,了解即可】
匿名内部类【重点】
每一个内部类也都会有一个单独的.class文件
3.权限修饰符
3.1四个权限修饰符
public > protected > 空的 > private
3.2访问范围
本类中 | 本包中 | 不同包的子类中 | 不同包中 | |
---|---|---|---|---|
public | Y | Y | Y | Y |
protected | Y | Y | Y | |
空的 | Y | Y | ||
private | Y |
- 代码演示
package com.itheima_07;
public class AAA {
//公共的
public void method1(){
System.out.println("public");
}
//受保护的
protected void method2(){
System.out.println("protected");
}
//空的
void method3(){
System.out.println("空的");
}
//私有的
private void method4(){
System.out.println("private");
}
//当前类
public void show(){
method1();
method2();
method3();
method4();
}
}
public class BBB {
public static void main(String[] args) {
AAA a = new AAA();
a.method1();
a.method2();
a.method3();
//a.method4();
}
}
package com.itheima_08;
import com.itheima_07.AAA;
//不同包下的子类
//可以使用public和protected的方法
public class CCC extends AAA{
public void show(){
method1();
method2();
//method3();
//method4();
}
}
//不同包
public class DDD {
public static void main(String[] args) {
AAA a = new AAA();
a.method1();
//a.method2();
//a.method3();
//a.method4();
}
}
3.3 权限修饰符的作用位置【不用记】
类:public 空的
成员变量:四个都能用
成员方法:四个都能用
构造方法:四个都能用
局部变量:没有权限修饰符
4.代码块
4.1静态代码块
-
格式:
static{ 要执行的代码 }
-
执行时机:
在当前类第一次被使用的时候静态代码块会执行,且只执行一次
-
代码演示:
public class AAA { static int a = 10; //静态代码块 //在AAA类第一次被使用的时候,静态代码块会自动执行 static{ System.out.println("静态代码块"); } } public class Demo测试类 { public static void main(String[] args) { //创建对象 //AAA a1 = new AAA(); //AAA a2 = new AAA(); System.out.println(AAA.a); //10 } } 执行效果: 静态代码块 10
-
使用场景:
如果有些代码只需要执行一次且需要在别的代码之前执行,就可以放在静态代码块中,比如加载驱动。
4.2构造代码块
-
格式:
在类中方法外: { 里面可以写代码; }
-
执行时机:
在构造方法执行的最开始先执行构造代码块
-
代码演示:
public class BBB { String name; //姓名 int age; //年龄 //构造代码块 //会在每个构造方法执行时候先执行构造代码块 { System.out.println(1); System.out.println(2); System.out.println(3); } //空参构造 public BBB() { } //有参构造 public BBB(String name, int age) { this.name = name; this.age = age; } } public class Demo构造代码块测试 { public static void main(String[] args) { //使用空参构造创建对象 BBB b = new BBB(); //使用有参构造创建对象 BBB b2 = new BBB("柳岩",36); } } 执行结果: 1 2 3 1 2 3
-
使用场景:
多个构造方法中有相同的代码,为了提高代码复用性,可以把相同的代码抽取到构造代码块中
4.3局部代码块
-
格式:
方法中: { 可以写代码; }
-
作用:
限制变量的作用域,节约内存空间。
-
代码演示:
public class Demo局部代码块测试 { public static void main(String[] args) { int a = 10; //局部代码块 //变量b的作为范围只能在局部代码块中 { int b = 20; } System.out.println(a); //System.out.println(b); 超出作用域就不能使用 //在java中为了节约内存设计过很多技术点,但是现在内存不值钱了,所以这些技术也就慢慢不用了. } }
4.4代码块执行顺序演示
public class CCC {
//静态代码块
static{
System.out.println(1);
}
//构造代码块
{
System.out.println(2);
}
//构造方法
public CCC(){
System.out.println(3);
}
}
public class Demo练习测试 {
public static void main(String[] args) {
//创建对象
CCC c = new CCC();
CCC c2 = new CCC();
}
}
执行效果:
1
2
3
2
3
总结
多态
成员访问特点
成员变量【记】
成员方法【记】
优缺点
缺点【记】
优点【记】
类型转换
向上转型【记】
向下转型【记】
ClassCastException异常【理解不用记】
instanceof【练】
笔记本案例【练】
内部类
成员内部类【理解就ok】
局部内部类【不用】
匿名内部类【记】
权限修饰符
四个权限修饰符
public 【常用】
protected
空的
private【常用】
代码块
静态代码块【记】
构造代码块【不常用】
局部代码块【赶紧忘掉】