导读
1.抽象类
2.接口
3.接口的默认方法与静态方法
4.内部类
5.匿名内部类补充详解
6.接口中的内部类
抽象类
规则6:一个类继承抽象类后,必须实现其所有的抽象方法,否则也得是抽象类,不同的子类对父类的抽象方法可以有不同的实现
规则7:
规则8:
Animal父类
package com.hala.animal;
public abstract class Animal {
protected String name;
private int math;
private String species;
//父类构造方法不能被继承,不能被重写
public Animal(){
}
public Animal(String name,int math){
this.setName(name);
this.setMath(math);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMath() {
return math;
}
public void setMath(int math) {
this.math = math;
}
public String getSpecies() {
return species;
}
public void setSpecies(String species) {
this.species = species;
}
//抽象方法,不允许包含方法体,子类中需要重写父类的抽象方法
public abstract void eat();
}
Cat子类
package com.hala.animal;
public class Cat extends Animal {
private double weight;
public Cat(){
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
//跑动方法
public void run(){
System.out.println("小猫正在跑。");
}
//子类必须实现父类的抽象方法
@Override
public void eat() {
System.out.println("小猫会吃鱼");
}
}
接口
TelPhone类
package com.hala.tel;
public class TelPhone {
private String brand;
private int price;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
//打电话
public void call(){
System.out.println("手机可以打电话");
}
}
SecondPhone类
package com.hala.tel;
public class SecondPhone extends TelPhone {
//发短信·
public void message(){
System.out.println("手机可以发短信");
}
}
ThirdPhone类
package com.hala.tel;
public class ThirdPhone extends SecondPhone {
public void video(){
System.out.println("手机可以看视频");
}
public void music(){
System.out.println("手机可以听音乐");
}
}
ForthPhone 类
package com.hala.tel;
//此处为实现接口的语法
public class ForthPhone extends ThirdPhone implements IPhoto,INet{
public void game(){
System.out.println("手机可以玩游戏");
}
@Override
public void photo() {
// TODO Auto-generated method stub
System.out.println("手机可以拍照");
}
@Override
public void connection() {
// TODO Auto-generated method stub
System.out.println("手机可以连接");
}
@Override
public void network() {
// TODO Auto-generated method stub
System.out.println("手机可以上网");
}
}
Computer类
package com.hala.tel;
public class Computer implements INet{
@Override
public void network() {
System.out.println("电脑可以上网");
}
}
Creame类
package com.hala.tel;
public class Creame implements IPhoto {
@Override
public void photo() {
// TODO Auto-generated method stub
System.out.println("相机可以拍照");
}
@Override
public void connection() {
// TODO Auto-generated method stub
System.out.println("相机可以连接");
}
}
INet接口
package com.hala.tel;
/**
*
* 具有上网能力的接口
* @author hala
*
*/
public interface INet {
public void network();
}
IPhoto接口
package com.hala.tel;
/**
* 1.接口的命名通常以 i打头,这是一种习惯
* 2. 接口的访问权限为public或默认不可以是private或protected
* 具有照相能力的接口
* @author hala
*
*/
public interface IPhoto {
//具有拍照的能力,注意此处没有方法体
//接口中抽象方法可以不写abstract关键字
//若此处省略public也是可以的,但系统还是会默认为public
public void photo();
//当类实现一个接口时,需要去实现接口中所有抽象方法,否则要把类设置为抽象类
public void connection();
//接口中可以包含常量,默认为public static final
//注意要赋初值
int TEMP=20;
}
PhoneTest测试类
package com.hala.test;
import com.hala.tel.Computer;
import com.hala.tel.Creame;
import com.hala.tel.ForthPhone;
import com.hala.tel.INet;
import com.hala.tel.IPhoto;
import com.hala.tel.SmartWatch;
public class PhoneTest {
public static void main(String[] args) {
IPhoto photo=new Creame();
photo.photo();
photo=new ForthPhone();
photo.photo();
//这里TEMP可以直接用IPhoto调用,因为它是默认为static的
//也可以在类中定义TEMP但优先调用interface
System.out.println(IPhoto.TEMP);
INet net=new Computer();
net.network();
net=new SmartWatch();
net.network();
}
}
输出结果
相机可以拍照
手机可以拍照
20
电脑可以上网
手表可以上网
接口的默认方法与静态方法
接口IPhoto
package com.hala.tel;
/**
* 1.接口的命名通常以 i打头,这是一种习惯
* 2. 接口的访问权限为public或默认不可以是private或protected
* 具有照相能力的接口
* @author hala
*
*/
public interface IPhoto {
public void photo();
//default:默认方法,可以带方法体(jdk1.8后)
//类实现此接口时不必实现此方法
//可以被重写
default public void connection(){
System.out.println("我是接口中的默认连接");
}
//static:静态方法,也可以带方法体(jdk1.8后)
//类实现此接口时不必实现此方法
//不可以被重写
public static void stop(){
System.out.println("我是接口中的静态方法");
}
int TEMP=20;
}
Creame类
package com.hala.tel;
public class Creame implements IPhoto {
@Override
public void photo() {
// TODO Auto-generated method stub
System.out.println("相机可以拍照");
}
//此方法可以不写,是对接口中该方法的重写,注意此处没有了default
@Override
public void connection() {
//调用接口中默认的方法
IPhoto.super.connection();
}
}
PhotoTest测试类
package com.hala.test;
import com.hala.tel.Computer;
import com.hala.tel.Creame;
import com.hala.tel.ForthPhone;
import com.hala.tel.INet;
import com.hala.tel.IPhoto;
import com.hala.tel.SmartWatch;
public class PhoneTest {
public static void main(String[] args) {
IPhoto photo=new Creame();
//调用默认方法时的操作
photo.connection();
//调用静态方法时的操作,只能用接口调用
IPhoto.stop();
}
}
输出结果
我是接口中的默认连接
我是接口中的静态方法
⚠️修改类名的方法 右击->refactor->rename
关于多接口中重名常量处理的解决方案
1.若一个类实现了两个接口,两个接口中含有重名的方法,那么要在类中重写这个方法
2.若这个类继承的父类里也含有这个重名方法,那么它会默认调用父类的方法,当然像上边一样重写也是可以的
3.对于方法的处理并不适用于属性,对于同名的接口属性在使用时要用interface.著名,对于父类中的同名属性要在子类中重新定义自己的
接口的继承
一个类只能有一个父类,但一个接口可以有多个父接口,如果父接口出现重名方法,则要在子接口中重写这个方法
接口与抽象类的比较
内部类
成员内部类(普通内部类)
Person类
package com.hala.people;
//外部类
public class Person {
int age;
public Heart getHeart(){
return new Heart();
}
public void eat(){
System.out.println("人会吃东西");
}
//成员内部类
/*
* 1.内部类在外部使用时,无法直接实例化,需要借助外部类信息完成实例化
* 2.内部类的访问修饰符可以任意,但访问的范围与一般规则相同
* 3.内部类可以直接访问外部类成员(属性,方法),如果出现同名属性优先访问内部类定义的
* 4.同名属性情况,可以使用外部类.this.成员,访问外部类的同名信息
* 5.外部类调用内部类信息,需要通过内部类实例,无法直接访问
* 6.内部类编译后.class文件命名:外部类$内部类.class
*/
class Heart{
public String beat(){
eat();
return age+"岁的心脏会跳动";
}
}
}
PeopleTest类
package com.hala.people;
public class PeppleTest {
public static void main(String[] args) {
Person lili=new Person();
lili.age=12;
//获取内部类对象实例,方式1:new 外部类.new 内部类
//这里注意会出现0岁是因为此方法重新定义了一个Person不是lili
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());
}
}
输出结果
人会吃东西
0岁的心脏会跳动
人会吃东西
12岁的心脏会跳动
人会吃东西
12岁的心脏会跳动
内部类与外部类同名属性情况
class Heart{
int age=14;
public String beat(){
eat();
return age+"岁的心脏会跳动";
}
}
}
输出结果
人会吃东西
14岁的心脏会跳动
人会吃东西
14岁的心脏会跳动
人会吃东西
14岁的心脏会跳动
同名情况调用外部类信息
class Heart{
int age=14;
public String beat(){
eat();
return Person.this.age+"岁的心脏会跳动";
}
}
}
输出结果
人会吃东西
0岁的心脏会跳动
人会吃东西
12岁的心脏会跳动
人会吃东西
12岁的心脏会跳动
⚠️查看项目在系统中目录结构方法:右键项目->show in->System Explorer
外部类调用内部类信息
package com.hala.people;
public class Person {
int age;
public Heart getHeart(){
new Heart().age=13;
return new Heart();
}
public void eat(){
System.out.println("人会吃东西");
}
class Heart{
int age=14;
public String beat(){
eat();
return Person.this.age+"岁的心脏会跳动";
}
}
}
内部类编译后.class文件命名
静态内部类
Person类
package com.hala.people;
public class Person {
int age;
static int month=3;
public Heart getHeart(){
new Heart().age=13;
return new Heart();
}
public void eat(){
System.out.println("人会吃东西");
}
//静态内部类
/*
* 1.静态内部类中,只能直接访问外部类的静态成员,如果需要调用非静态成员,可以通过对象实例
* 2.静态内部类对象实例化时,可以不依赖于外部类对象
* 3.可以通过外部类.内部类.静态成员的方式,访问内部类中的静态成员
* 4.当内部类属性与外部类属性相同时,默认会直接调用内部类属性
* 如果需要访问外部类中的静态属性,方法:外部类.属性
* 如果需要访问外部类的非静态属性,方法:new 外部类().属性
*/
static class Heart{
int age=14;
public static void say(){
System.out.println("hello");
}
public String beat(){
new Person().eat();
return new Person().age+"岁"+Person.month+"月的心脏会跳动";
}
}
}
PeopleTest类
package com.hala.people;
public class PeppleTest {
public static void main(String[] args) {
Person lili=new Person();
lili.age=12;
//获取静态内部类对象实例
Person.Heart myHeart=new Person.Heart();
System.out.println(myHeart.beat());
Person.Heart.say();
}
}
输出结果
人会吃东西
0岁3月的心脏会跳动
hello
方法内部类(局部内部类)
Person类
package com.hala.people;
public class Person {
int age;
public Object getHeart() {
//方法内部类
/*
* 1.定义在方法内部,作用范围也在方法内
* 2.和方法内部成员使用规则一样,class前不允许添加public,private,protected,static
* 3.类中不能包含静态成员
* 4.类中可以包含final,abstract修饰的成员
*/
class Heart {
int age = 14;
public void say() {
System.out.println("hello");
}
public String beat() {
say();
return new Person().age+"岁的心脏在跳动";
}
}
return new Heart().beat();
}
}
PeopleTest类
package com.hala.people;
public class PeppleTest {
public static void main(String[] args) {
Person lili=new Person();
lili.age=12;
System.out.println(lili.getHeart());
}
}
输出结果
hello
0岁的心脏在跳动
方法内部类文件命名的不同之处
匿名内部类
Person类
package com.hala.people;
public abstract class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public abstract void read();
}
PeopleTest类
package com.hala.people;
public class PeopleTest {
public void getRead(Person person){
person.read();
}
public static void main(String[] args) {
PeopleTest test=new PeopleTest();
//匿名内部类
/*
* 1.匿名内部类没有类型名称,没有实例对象名称
* 2.无法使用private,abstract,static 等修饰
* 3.无法编写构造方法,但可以添加构造代码块
* 4.不能出现静态成员,abstaract方法
* 5.匿名内部类可以实现接口也可以继承父类,但只能二选一
*/
test.getRead(new Person(){
@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("女生喜欢读言情小说");
}
});
}
}
输出结果
男人喜欢看科幻小说
女生喜欢读言情小说
匿名内部类文件命名