Java面向对象-接口-内部类
一、接口(interface)
1. 理解
2. 基本内容
1. 接口,使用interface关键字来定义
* 2. 接口,是与类并列的结构
*
* 3. jdk7及之前:接口中只能定义全局常量(public static final)和抽象方法(public abstract)。
* 常量的public static final可以省略
* 抽象方法的public abstract也可以省略
*
* jdk8中: 接口中还可以定义静态(static)方法和默认(default)方法.
* jdk9中:接口中还可以定义私有(private)方法
*
* 明确:接口中没有构造器!接口不可以实例化
*
* 4. 类与接口之间是实现关系:implements
* 类实现接口以后,如果实现了接口中的所有的抽象方法,则此类不是抽象类,可以实例化
* 如果实现类没有实现接口中的所有的抽象方法的话,则此类就是一个抽象类,不能实例化。
* 5. 类可以实现多个接口。比如:class Bullet extends Object implements Flyable,Attackable
*
* 6. 接口与接口之间是继承关系。而且是可以多继承的!
3. 代码体现
public class InterfaceTest {
public static void main(String[] args) {
System.out.println(Flyable.MAX_SPEED);
// Flyable.MAX_SPEED = 4500;
Plane p = new Plane();
p.fly();
Flyable f = p;//体现了接口的多态性
method(p);
}
public static void method(Flyable f){
f.fly();
}
}
interface Flyable{ //可以飞的接口
//常量
public static final int MIN_SPEED = 1;
int MAX_SPEED = 7900;//第一宇宙速度
//抽象方法
public abstract void fly();
void stop();
}
interface Attackable{
void attack();
}
class Plane implements Flyable{//Plane has a Flyable
@Override
public void fly() {
System.out.println("飞行员启动飞机飞行");
}
@Override
public void stop() {
System.out.println("飞行员控制飞机停止飞行");
}
}
abstract class Kite implements Flyable{ //Kite has a Flyable
}
class Bullet implements Flyable,Attackable,C{
@Override
public void attack() {
// TODO Auto-generated method stub
}
@Override
public void fly() {
// TODO Auto-generated method stub
}
@Override
public void stop() {
// TODO Auto-generated method stub
}
@Override
public void test1() {
// TODO Auto-generated method stub
}
@Override
public void test2() {
// TODO Auto-generated method stub
}
}
//*************************************
interface A{
void test1();
}
interface B{
void test2();
}
interface C extends A,B{//接口的多继承
}
4. 接口体现多态性
class Computer{
public void transferData(USB usb){ //USB usb = new Flash();
usb.start();
System.out.println("usb设备开始进行数据的传输....");
usb.stop();
}
}
interface USB{
//常量:尺寸(略)
//抽象方法
public abstract void start();
void stop();
}
class Flash implements USB{
@Override
public void start() {
System.out.println("U盘开始工作");
}
@Override
public void stop() {
System.out.println("U盘结束工作");
}
}
class Printer implements USB{
@Override
public void start() {
System.out.println("打印机开始工作");
}
@Override
public void stop() {
System.out.println("打印机结束工作");
}
}
public class USBTest {
public static void main(String[] args) {
Computer c1 = new Computer();
//1. 创建接口实现类的非匿名对象
Flash flash = new Flash();
c1.transferData(flash);
}
}
5. 接口的匿名实现类、匿名对象
public class USBTest {
public static void main(String[] args) {
Computer c1 = new Computer();
//1. 创建接口实现类的非匿名对象
Flash flash = new Flash();
c1.transferData(flash);
//2. 创建接口实现类的匿名对象
c1.transferData(new Printer());
//3. 创建接口匿名实现类的非匿名对象
USB usb1 = new USB(){
@Override
public void start() {
System.out.println("mp3开始工作");
}
@Override
public void stop() {
System.out.println("mp3结束工作");
}
};
c1.transferData(usb1);
//4. 创建接口匿名实现类的匿名对象
c1.transferData(new USB(){
@Override
public void start() {
System.out.println("手机开始工作");
}
@Override
public void stop() {
System.out.println("手机结束工作");
}
});
}
}
类似的:抽象类也有同样的使用
public class AbstractTest {
public static void main(String[] args) {
Student s1 = new Student();
//创建了抽象类的匿名子类的对象
Person p1 = new Person(){
@Override
public void eat() {
System.out.println("工人多吃肉!");
}
};
// Person p2 = new Person(){};
}
}
abstract class Person{
public abstract void eat();
public void sleep(){
System.out.println("人睡觉");
}
}
class Student extends Person{
@Override
public void eat() {
}
}
6. 练习
面试题1:是否能正常执行
interface A {
int x = 0;
}
class B {
int x = 1;
}
class C extends B implements A {
public void pX() {
System.out.println(x);
}
public static void main(String[] args) {
new C().pX();
}
}
答案:
//编译错误。
//System.out.println(x);
//修改:
System.out.println(super.x);
System.out.println(A.x);
面试题2:是否能正常执行
interface Playable {
void play();
}
interface Bounceable {
void play();
}
interface Rollable extends Playable, Bounceable {
Ball ball = new Ball("PingPang");
}
class Ball implements Rollable {
private String name;
public String getName() {
return name;
}
public Ball(String name) {
this.name = name;
}
public void play() {
ball = new Ball("Football");
System.out.println(ball.getName());
}
}
答案:
Ball类中的play()中的ball不能再被赋值。因为是常量
代码题:
定义一个接口用来实现两个对象的比较。
interface CompareObject{
public int compareTo(Object o); //若返回值是 0 , 代表相等; 若为正数,代表当前对象大;负数代表当前对象小
}
定义一个Circle类,声明redius属性,提供getter和setter方法
定义一个ComparableCircle类,继承Circle类并且实现CompareObject接口。在ComparableCircle类中给出接口中方法compareTo的实现体,用来比较两个圆的半径大小。
定义一个测试类InterfaceTest,创建两个ComparableCircle对象,调用compareTo方法比较两个类的半径大小。
思考:参照上述做法定义矩形类Rectangle和ComparableRectangle类,在ComparableRectangle类中给出compareTo方法的实现,比较两个矩形的面积大小。
答案:
public interface CompareObject {
// 若返回值是 0,代表相等; 若为正数,代表当前对象大;负数代表当前对象小
public int compareTo(Object o);
}
/*
* 定义一个Circle类,声明redius属性,提供getter和setter方法
*/
public class Circle {
private double radius;//半径
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
public Circle() {
super();
}
public Circle(double radius) {
super();
this.radius = radius;
}
@Override
public String toString() {
return "Circle [radius=" + radius + "]";
}
}
/*
* 定义一个ComparableCircle类,继承Circle类并且实现CompareObject接口。
* 在ComparableCircle类中给出接口中方法compareTo的实现体,用来比较两个圆的半径大小。
*/
public class ComparableCircle extends Circle implements CompareObject {
public ComparableCircle() {
super();
}
public ComparableCircle(double radius) {
super(radius);
}
@Override
public int compareTo(Object o) {
if(o == this){
return 0;
}
if(o instanceof ComparableCircle){
ComparableCircle c = (ComparableCircle)o;
//不够准确的情况:
// return (int) (this.getRadius() - c.getRadius());
//写法一:
// if(this.getRadius() > c.getRadius()){
// return 1;
// }else if(this.getRadius() < c.getRadius()){
// return -1;
// }else{
// return 0;
// }
//写法二:
return Double.compare(this.getRadius(), c.getRadius());
}else{
//形参o不是一个ComparableCircle类型的对象
return -2;
// throw new RuntimeException("输入的类型不匹配");
}
}
}
/*
* 定义一个测试类InterfaceTest,
* 创建两个ComparableCircle对象,调用compareTo方法比较两个类的半径大小。
*/
public class InterfaceTest {
public static void main(String[] args) {
ComparableCircle c1 = new ComparableCircle(2.3);
ComparableCircle c2 = new ComparableCircle(2.4);
int compareValue = c1.compareTo(c2);
System.out.println(compareValue);
//语法错误的
// c1.getRadius() += 2; //c1.getRadius() = c1.getRadius() + 2;
// c1.compareTo(c2) += 3;
}
}
7. 接口的应用之一
- 代理模式
- 工厂方法模式
8. java8中的新特性
//从java8开始,可以在接口中定义静态方法和默认方法。
public interface CompareA {
public static void method1(){
System.out.println("CompareA:北京");
}
public default void method2(){
System.out.println("CompareA:上海");
}
//如下的方法也是public,只是省略了
default void method3(){
System.out.println("CompareA:深圳 ");
}
default void method4(){
System.out.println("CompareA:广州 ");
}
}
public interface CompareB {
default void method3(){
System.out.println("CompareB:深圳 ");
}
}
public class SuperClass {
public void method4(){
System.out.println("SuperClass:广州");
}
}
public class SubClass extends SuperClass implements CompareA,CompareB{
//重写了接口中的method2()方法
public void method2(){
System.out.println("SubClass:上海");
}
public void method3(){
System.out.println("SubClass:深圳 ");
}
public void method4(){
System.out.println("SubClass:广州");
}
public void method(){
method4();//调用本类重写的方法
super.method4();//调用父类中被重写的方法
CompareA.super.method3();//调用接口CompareA中的method3()
CompareB.super.method3();//调用接口CompareB中的method3()
}
}
public class InterfaceTest {
public static void main(String[] args) {
//知识点1:通过接口调用其内部的静态方法。但是实现类不可以调用其静态方法
CompareA.method1();
// SubClass.method1();
//知识点2:通过实现类的对象调用接口中的默认方法
SubClass sub = new SubClass();
sub.method3();
//知识点3:如果实现类重写了接口中的默认方法,则实现类对象调用的就是重写以后的方法
sub.method2();
//知识点4:如果实现类实现了两个以上的接口。而至少有两个接口中定义了同名同参数的默认方法,则实现类
//必须重写此方法。否则,报异常--->接口冲突
//知识点5:如果子类(或实现类)继承的父类和实现的接口中定义了同名同参数的方法,则不会报冲突问题
//在子类(或实现类)没重写此方法的情况下,默认调用的是父类中的方法。--->类优先原则
sub.method4();
System.out.println();
//知识点6:如何在实现类中调用接口的被重写的默认方法
sub.method();
}
}
四、类的成员之五:内部类(InnerClass)
1. 基本内容
1. 理解:我们可以在一个类A的内部定义另一个类B,则此时类B就称为类A的内部类,类A就称为类B的外部类
*
* 2. 内部类的分类:成员内部类 (静态的、非静态的) vs 局部内部类(方法内、代码块内、构造器内)
*
* 3. 成员内部类的理解:
* 3.1 成员内部类作为一个类:
* > 内部可以定义属性、方法、构造器、代码块、内部类
* > 可以被abstract修饰,表示不能实例化
* > 可以被final修饰,表示不能被继承
*
* 3.2 成员内部类作为外部类的成员:
* > 可以被4种权限修饰符修饰
* > 可以被static修饰
* > 可以调用外部类的结构(主要是属性、方法)
4. 关于内部类需要掌握的三个方面:
* > 如何创建静态的和非静态的成员内部类的对象
* > 如何在内部类中调用外部类的成员
* > 局部内部类在开发中的体现
2. 成员内部类的使用
* > 如何创建静态的和非静态的成员内部类的对象
* > 如何在内部类中调用外部类的成员
class Person{
String name = "连志鹏";
int age;
//成员内部类
static class Dog{
public void shout(){
System.out.println("汪~汪~");
}
}
class Bird{
String name = "麻雀";
public void show(String name){
System.out.println(name);//黄鹂
System.out.println(this.name);//麻雀
System.out.println(Person.this.name);//连志鹏
}
public void sing(){
System.out.println("鸟儿在歌唱");
eat();
System.out.println(age);//Person.this.age
}
}
public void show(){
System.out.println("name : " +name + ", age : " + age);
}
public void eat(){
System.out.println("人吃饭");
}
}
public class OuterClass {
public static void main(String[] args) {
//创建静态的成员内部类的对象
Person.Dog dog = new Person.Dog();
dog.shout();
//创建非静态的成员内部类的对象
Person p1 = new Person();
p1.age = 12;
Person.Bird bird = p1.new Bird();
bird.sing();
bird.show("黄鹂");
}
}
3. 局部内部类的使用
//局部内部类在开发中的体现
public class OuterClass1 {
public void method(){
//局部内部类
//此种情况在开发中很少见
class A{
}
}
//返回接口实现类的对象
public Comparable getComparable(){
//方式一:声明一个接口的实现类
// class MyComparable implements Comparable{
//
// @Override
// public int compareTo(Object o) {
// return 0;
// }
//
// }
// return new MyComparable();
//方式二:创建接口的匿名实现类的匿名对象
return new Comparable(){
@Override
public int compareTo(Object o) {
return 0;
}
};
/*
*
* button.setOnClick(new ClickListener(){
* public void onClick(){
* //当点击按钮时,希望触发的操作
* }
* });
*
*
*
*/
}
}
4. 关于内部类编译后生成的字节码文件
对应的类为:
class Person{
String name = "连志鹏";
int age;
//成员内部类
static class Dog{
public void shout(){
System.out.println("汪~汪~");
}
}
class Bird{
String name = "麻雀";
public void show(String name){
System.out.println(name);//黄鹂
System.out.println(this.name);//麻雀
System.out.println(Person.this.name);//连志鹏
}
public void sing(){
System.out.println("鸟儿在歌唱");
eat();
System.out.println(age);//Person.this.age
}
}
public void show(){
System.out.println("name : " +name + ", age : " + age);
}
public void eat(){
System.out.println("人吃饭");
}
//********************************
public void method(){
//局部内部类
class A{}
}
{
//局部内部类
class A{}
}
public Person(){
//局部内部类
class C{}
}
}
五、面向对象的小结
- 类与对象的理解和关系
- 面向对象编程的思路:
- 创建类
- 创建对象
- 通过"对象.属性"或"对象.方法"的方式进行功能的调用
声明:针对于工具类等结构,通常内部都是定义静态的属性或方法,直接通过类进行调用。
- 主线一:类的内部结构
- 属性
- 属性 vs 局部变量
- 方法(最重要)
- 方法的声明
- 方法的重载
- 方法的值传递机制
- 递归方法
- 方法的重写
- 构造器
- 创建对象、初始化对象的属性
- 构造器可以重载
- 构造器内部可以使用this(形参列表) 或 super(形参列表)
- 代码块
- 作用:初始化类或对象的基本信息
- 分类
- 内部类
- 了解
- 成员内部类的使用
- 主线二 :面向对象的三大特征
- 封装性
- 狭义:private属性 public的getter()\setter()
- 广义:体现为4种权限修饰符
- 继承性
- 类的继承性:单继承
- 接口的继承性:多继承
- 多态性(难点)
- 子类对象的多态性
- 主线三:关键字的使用
- this
- import
- package
- super
- static
- final
- abstract
- interface
六、小结
- 接口(interface),与类(class)并列的结构
- 让类去实现(implements)接口,同时需要重写(或实现)接口中的抽象方法
- 类可以实现多个接口
- 接口,体现的是一种规范。比如:Serializable:可序列化;Comparable:可比较大小的
class String implements java.io.Serializable, Comparable
- 接口,内部只能定义全局常量和抽象方法 —jdk7及之前
- jdk8中,可以定义静态方法、默认方法
- jdk9中,可以定义私有方法
- 接口与实现类之间存在多态性
- 比如:public void compare(Comparable c){}
- 内部类
- 实际开发中,使用较少
- 理解:内部类的分类:成员内部类、局部内部类
- 如何实例化成员内部类
- 在成员内部类中如何调用外部类的结构:**外部类.this.**外部类的结构
- 局部内部类的使用:常常在方法内部提供接口的匿名实现类的对象。
- 题目:你是如何理解面向对象三大特征的? —> 你是如何理解面向对象编程思想的?
- 封装性:封装结构到类中;4种权限修饰符修饰类及类的内部结构,体现可见性的大小;举例
- 继承性:继承性的好处;类的单继承性
- 多态性:子类对象的多态性+虚方法调用;举例;如果没有多态性,抽象类和接口的声明就没有意义!
- 题目:“万事万物皆对象”,你是怎么理解的?
- 用java语言编写项目、描述客观世界,都需要由类派生的对象去刻画
- 层次一:字符串:String,数值类型:包装类,日期:Date,。。。。
- 层次二:文件:File;IP地址:InetAddress ; 具体网址:URL
- 层次三:Java语言与其他语言的交互:XML 、数据库、。。