Java多态(下)
接口
接口定义了某一批类所要遵守的规范,接口不关心这些类的内部数据,页不关心这些类里方法的实现细节,它只规定这些类里必须提供某些方法
语法:
[修饰符] interface 接口名 [ extends 父接口1,父接口2...]
{
零到多个常量定义...
零到多个抽象方法的定义...
零到多个默认方法的定义...(JDK1.8新增)
零到多个静态方法的定义...(JDK1.8新增)
}
接口的语法规则
- 接口及接口成员默认的访问权限为:public 或 默认
- 常量默认添加static final 关键字
- 抽象方法默认添加 abstract 关键字
- 只有 default 方法及 static 方法可以添加方法体
- 实现接口的类如果不能实现所以接口中待重写的方法,则必须设置为抽象类
- 接口可以实现多继承,即一个子接口可以同时继承多个父接口
- 一个类可以继承自一个父类,同时实现多个接口
- 当一个类同时实现多借口,且其中同时具有相同的方法时,实现类需重写该方法,否则会编译报错
内部类
在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类,与之对应,包含内部类的类被称为外部类
分类:
- 成员内部类
- 静态内部类
- 方法内部类
- 匿名内部类
成员内部类
内部类中最常见的成员内部类,也称为普通内部类
- 内部类相当于外部类的一个成员变量,可以使用任意访问修饰符
- 内部类中定义的方法可以直接访问外部类中的数据,而不受访问控制符的影响
- 外部类不能直接使用内部类的成员和方法,需要借用内部类对象完成
- 需要通过外部类对象来创建内部类实例
- 如果外部类和内部类具有相同的成员,内部类默认优先访问自己的成员;可以通过“ 外部类.this.对象成员” 以及 “外部类.静态成员” 的方式访问外部类成员
- 编译后产生:外部类$内部类.class
静态内部类
- 静态内部类对象实例时,可以不依赖于外部类对象
- 静态内部类中,只能直接访问外部类的静态成员,如果需要调用非静态成员,可以通过对象实例
- 可以通过外部类.内部类.静态成员的方式,访问内部类中的静态成员
- 当内部类属性与外部类属性同名时,默认直接调用内部类中的成员
- 如果需要访问外部类中的静态属性,则可以通过 外部类.属性 的方式
- 如果需要访问外部类中的非静态属性,则可以通过 new 外部类().属性的方式
方法内部类
- 定义在外部类方法中的内部类,也称局部内部类
- 方法内部类只在其定义所在的方法内部可见,即只在该方法内可使用
- 和方法内部成员使用规则一样,class前面不可以添加public、private、protected、static
- 类中可以包含final、abstract修饰的成员
- 编译后产生:外部类$数字》class
代码实现
Person类
package com.SH.people;
//外部类
public class Person {
public static int age;
// 方法内部类
/*
* 1、定义在方法内部,作用范围也在方法内
* 2、和方法内部成员使用规则一样,class前面不可以添加public、private、protected、static
* 3、类中不能包含静态成员
* 4、类中可以包含final、abstract修饰的成员
*/
public Object getHeart() {
class Heart {
public final int age = 13;
int temp = 22;
public final void say() {
System.out.println("hello");
}
public void eat() {
}
public String beat() {
new Person().eat();
return Person.age + "岁的心脏在跳动";
}
}
return new Heart().beat();
// new Heart().temp=12;
temp=33;
// return new Heart();
}
public void eat() {
System.out.println("人会吃东西");
}
// 成员内部类
/*
* 1、内部类在外部使用时,无法直接实例化,需要借由外部类信息才能完成实例化
* 2、内部类的访问修饰符,可以任意,但是访问范围会受到影响
* 3、内部类可以直接访问外部类的成员;如果出现同名属性,优先访问内部类中定义的
* 4、可以使用外部类.this.成员的方式,访问外部类中同名的信息
* 5、外部类访问内部类信息,需要通过内部类实例,无法直接访问
* 6、内部类编译后.class文件命名:外部类$内部类.class
* 7、内部类中是否可以包含与外部类相同方法签名的方法?以及如何调用?
*/
/*
public class Heart1 {
int age = 13;
int temp = 22;
// public void eat(){....}
public String beat() {
eat();
return Person.this.age + "岁的心脏在跳动";
}
}
*/
// 静态内部类
/*
* 1、静态内部类中,只能直接访问外部类的静态成员,如果需要调用非静态成员,可以通过对象实例
* 2、静态内部类对象实例时,可以不依赖于外部类对象
* 3、可以通过外部类.内部类.静态成员的方式,访问内部类中的静态成员
* 4、当内部类属性与外部类属性同名时,默认直接调用内部类中的成员;
* 如果需要访问外部类中的静态属性,则可以通过 外部类.属性 的方式;
* 如果需要访问外部类中的非静态属性,则可以通过 new 外部类().属性的方式;
*/
/* public static class Heart {
public static int age = 13;
int temp = 22;
public static void say() {
System.out.println("hello");
}
public void eat() {
}
public String beat() {
new Person().eat();
return Person.age + "岁的心脏在跳动";
}
}
*/
}
Test类
package com.SH.test;
import com.SH.people.Person;
//import com.imooc.people.Person.Heart;
public class PeopleTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Person lili=new Person();
lili.age=12;
/*
//获取成员内部类对象实例,方式1:new 外部类.new 内部类
Person.Heart myHeart=new Person().new Heart();
System.out.println(myHeart.beat());
//获取成员内部类对象实例,方式2:外部类对象.new 内部类
myHeart=lili.new Heart();
System.out.println(myHeart.beat());
//获取成员内部类对象实例,方式3:外部类对象.获取方法
myHeart=lili.getHeart();
System.out.println(myHeart.beat());
*/
/*
//获取静态内部类对象实例
Person.Heart myHeart=new Person.Heart();
System.out.println(myHeart.beat());
Person.Heart.say();
*/
System.out.println(lili.getHeart());
}
}
匿名内部类
- 适用场景:
-只用到类的一个实例
-类在定义后马上用到
-给类命名并不会导致代码更容易被理解 - 使用原则:
- 不能有构造方法,可以通过构造代码块实现数据初始化
- 不能定义任何静态成员,静态方法
- 不能使用private、public、protected、abstract、static修饰
- 因匿名内部类也是局部内部类,所以局部内部类的所以限制对其都生效
- 一个匿名内部类一定时在new后面,用其隐含实现一个接口或继承一个类,但是两者不可兼得
- 只能创建匿名内部类的一个实例
- 匿名内部类在编译时候由系统自动起名为Outer$1.class
- 一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或重写
- 通过匿名内部类返回的时一个对象的引用,所以可以直接使用或将其复制给一个对象变量
代码实现
Person类
package com.SH.anonymous;
public abstract class Person {
private String name;
public Person(){
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public abstract void read();
}
Man类
package com.SH.anonymous;
//public class Man extends Person {
//
// @Override
// public void read() {
// // TODO Auto-generated method stub
// System.out.println("男生喜欢看科幻类书籍");
// }
//
//}
Woman类
package com.SH.anonymous;
//public class Woman extends Person {
//
// @Override
// public void read() {
// // TODO Auto-generated method stub
// System.out.println("女生喜欢读言情小说");
// }
//
//}
Test类
package com.SH.test;
//import com.SH.anonymous.Man;
import com.SH.anonymous.Person;
//import com.SH.anonymous.Woman;
public class PersonTest {
//根据传入的不同的人的类型,调用对应的read方法
//方案1:
// public void getRead(Man man){
// man.read();
// }
// public void getRead(Woman woman){
// woman.read();
// }
//方案2:
public void getRead(Person person){
person.read();
}
//
public static void main(String[] args) {
PersonTest test=new PersonTest();
// Man one=new Man();
// Woman two=new Woman();
// test.getRead(one);
// test.getRead(two);
//方案3:匿名内部类
/*
* 1、匿名内部类没有类型名称、实例对象名称
* 2、编译后的文件命名:外部类$数字.class
* 3、无法使用private、public、protected、abstract、static修饰
* 4、无法编写构造方法,可以添加构造代码块
* 5、不能出现静态成员
*/
test.getRead(new Person(){
{
//构造代码块
}
// public static int age=12;
@Override
public void read() {
// TODO Auto-generated method stub
System.out.println("男生喜欢看科幻类书籍");
}
});
test.getRead(new Person(){
@Override
public void read() {
// TODO Auto-generated method stub
System.out.println("女生喜欢读言情小说");
}
});
}
}
总结
- 多态
- 类型转换
- 抽象类&抽象方法
- 接口
- 内部类