接口
接口之间的多继承
注意:
- 多个父接口当中的抽象方法如果重复,没关系
- 多个父接口默认方法如果重复,那么子接口必须进行默认方法的重写,且default不能省略
多态
一些概念
- extends继承或者implements实习,是多态的前提
- 多态针对的是对象,一个对象拥有多种形态为对象的多态
- 父类引用指向子类对象
定义
父类名称 对象名 = new 子类名称();
接口名称 对象名 = new 实现类();
public class Father {
public void method(){
System.out.println("父类方法");
}
public void methodFu(){
System.out.println("父类特有");
}
}
public class son extends Father{
public void method(){
System.out.println("子类方法");
}
}
public class Main {
public static void main(String[] args) {
Father test = new son();
test.method();
}
}
成员变量&成员方法的使用
访问的方式:
- 直接通过对象访问
等号左边是谁优先用谁,没有则向上找,不会向下查找;
- 间接通过方法访问
方法属于谁优先用谁,没有则向上找,不会向下查找;
案例:
public class Father {
int num = 10;
public void method(){
System.out.println("父类方法");
}
}
public class son extends Father{
int num =20;
int age=11;
public void method(){
System.out.println("子类方法");
System.out.println(num);//优先使用子类的num
}
}
public class Main {
public static void main(String[] args) {
Father test = new son();
test.method();//调用的是子类的方法
//test.age=20; 错误,Father类中无age
System.out.println(test.num);//输出的是Father类的num
}
}
关于多态的小口诀
成员变量:编译看左,运行看左
成员方法:编译看左,运行看右
例子:
public class Father {
int num = 10;
public void method(){
System.out.println("父类方法");
}
public void methodFu(){
System.out.println("父类特有");
}
}
public class son extends Father{
int num =20;
int age=11;
public void method(){
System.out.println("子类方法");
System.out.println(num);
}
public void methodZi(){
System.out.println("子类特有的方法");
}
}
public class Main {
public static void main(String[] args) {
Father test = new son();
//编译时,Father类中有该函数所以编译通过,运行时子类中也有该函数则优先调用
test.method();
//编译时Father类中无age所以编译不通过则错误
test.age=20;
//编译时,Father类中有num则编译通过,而运行时父类有num,则优先调用父类
System.out.println(test.num);//输出的是Father类的num
//编译时,Father类中无该函数,则编译不通过
test.methodZi() 错误
}
}
//在多态中,对象无法访问子类特有的方法
好处
对象转型
- 向上转型(多态)
含义:创建一个子类对象,把他当做父类
向上转型一定是安全的
- 向下转型
格式:子类名称 对象名 = (子类名称)父类对象
含义:将父类对象还原为本来的子类对象 例:son test1=(son)test;
Instanceof
用于判断一个父类对象原来的子类
对象 instanceof 类名称;
//会得到一个boolean值
if(test instanceof son){
System.out.println("test 原来的子类为 son");
}
final 关键字
修饰类
public final class 类名称 {
}
含义:该类无任何子类,但可以有父类
注意:一个类被final修饰,则该类所有成员方法不能被重写
修饰方法
修饰符 final 返回值类型 方法名称(参数列表){
//方法体
}
//修饰符如:public private;
//abstract 于 final 无法同时使用
修饰局部变量
final 数据类型 变量名称 ;
变量名称 = 值;
或
final 数据类型 变量名称 =值;
//只需保证有唯一一次赋值即可
//一次赋值终身不变
对于基本数据类型,不可改变的是数值,对于引用类型,不可改变的是地址;
final Student stu1 = new Student(1);
stu1 = new Student(2);//错误,stu1中的地址值改变
//但是stu1中的成员可以改变值
修饰成员变量
final 数据类型 变量名称 = 值;
//由于成员变量有默认值所以,我们必须赋值
//对于final的成员变量,要么直接赋值,要么通过构造方法赋值
//要保证在运行前有值
权限修饰符
修饰符/权限 | public | protected | 默认 | private |
---|---|---|---|---|
同一个类 | YES | YES | YES | YES |
同一个包 | YES | YES | YES | NO |
不同包子类 | YES | YES | NO | NO |
不同包非子类 | YES | NO | NO | NO |
内部类
一些概念
- 一个类的内部包含另一个类
分类
成员内部类
修饰符 class 外部类名称(){
修饰符 class 内部类名称(){
//……
}
//……
}
//内用外,随意访问
//外用内,要用外部类中的方法访问内部类,且要用内部类对象
//生成文件名为 外部类名$内部类名.class
//外部类
public class boy {
//内部类
public class redhot{
int num=10;
public void print(){
System.out.println(num);
System.out.println(str);
}
public static void ss(){
System.out.println("静态");
}
}
//外部成员变量
private String str = "hello";
//外部方法
public void printf(){
System.out.println(this.str);
}
//用外部类的方法访问内部,且要用内部类对象
public void scand(){
redhot.ss();//静态
//匿名方法
new redhot().print(); //使用对象,调用内部类
}
}
public class Main {
public static void main(String[] args) {
//间接访问
boy one = new boy();
//外部类对象调用外部类方法
one.printf();
//外部类对象调用外部类方法去调用内部类方法
one.scand();
//直接访问
boy.redhot two = new boy().new redhot();
two.print();
}
}
关于重名问题
public class test {
int num =10;
public class test2{
int num = 20;
public void print(){
int num = 30;
System.out.println(num); //30
System.out.println(this.num); //20
System.out.println(test.this.num); //10
//直接访问外部类重名成员
//格式:外部类名.this.内部类
}
}
}
关于重名问题
- 子类父类重名
- 接口子类重名
- 接口实现类重名
- 接口接口重名
- 抽象类实现类重名
- 外部类内部类重名
- 成员方法重名
- 成员变量重名
- 抽象方法重名
um = 30;
System.out.println(num); //30
System.out.println(this.num); //20
System.out.println(test.this.num); //10
//直接访问外部类重名成员
//格式:外部类名.this.内部类
}
}
}
# 关于重名问题
1. 子类父类重名
2. 接口子类重名
3. 接口实现类重名
4. 接口接口重名
5. 抽象类实现类重名
6. 外部类内部类重名
7. 成员方法重名
8. 成员变量重名
9. 抽象方法重名