- 接口
- 基础
- 实现接口和继承类的区别
- 接口的多态(回忆继承的多态) - 内部类
- 局部内部类
- 匿名内部类
- 成员内部类
- 静态内部类
接口
基础
- 语法:
定义接口
public interface USBinterface {
int n1=100;
default void fun1()//默认实现方法
{
System.out.println("fun1....");
}
public void fun2();//接口中默认就是抽象方法
public static void fun3()
{
System.out.println("fun3...");
}
}
类实现接口(可以用补全键ctrl+i)
public class Phone implements USBinterface{
@Override
public void fun1() {
USBinterface.super.fun1();
}
@Override
public void fun2() {
}
}
调用实现接口的方法
public class Computer {
public void work(USBinterface usb){
usb.fun1();
usb.fun2();
USBinterface.fun3();
}
public static void main(String[] args) {
Phone phone=new Phone();
Computer computer=new Computer();
computer.work(phone); //传入这个phone对象就体现了接口的多态
}
}
- 应用场景:提供统一的规范,如几种数据库连接,然后用来连接的类都实现这个接口,调用同样的方法
- 一个类实现接口,就必须实现所有方法
- 一个类可以实现多个接口
- 接口中的属性是,只能是final的,并且是public static final
- 一个接口不能继承其他类,但可以实现多个别的接口,用extends
实现接口和继承类的区别
比方说,孙悟空类继承了猴子类,但是孙悟空还会飞,所以他实现了飞这个功能的接口
继承的价值在于:解决代码的复用性和可维护性。
接口的价值在于:设计,设计好各种规范(方法),让其他类去实现这些方法,即更加的灵活。
接口的多态(回忆继承的多态)
接口的多态类似继承的多态
继承的多态:
首先说向上转型和向下转型
向上转型(Upcasting):
- 向上转型是从子类类型转换为父类类型的过程。
- 在向上转型中,子类的实例被赋给父类类型的变量。
- 这是自动进行的,不需要特殊的语法。
例子:Animal myanimal=new dog();//Animal是dog的父类
向下转型(Downcasting):
- 向下转型是从父类类型转换为子类类型的过程。
- 在向下转型中,需要使用强制类型转换,因为这是从一个更通用的类型到一个更具体的类型的转换。
例子:
Animal myanimal=new dog(); //Animal是dog的父类
if(myanimal instanceof dog)
{
dog mydog = (dog) myanimal;
}
instanceof的作用是,用于在运行时检查对象是否是特定类的实例或实现了特定接口,主要用于类型检查
在这个例子中,instanceof
用于检查 myAnimal
是否是 Dog
类的实例。这是在向下转型之前进行的一种安全性检查,以确保实际运行时对象是我们期望的类型。
接口的多态
向上转型:
多态参数:接口类型的变量可以指向实现了这个接口的对象实例
类似于继承中的多态:父类类型的变量可以指向继承了这个类的对象实例,即向上转型
向下转型:
用这个多态数组的例子来理解吧
USBinterface[] USB=new USBinterface[2];
USB[0]=new Phone();
USB[1]=new Camera();
for (int i = 0; i < USB.length; i++) {
USB[i].fun1();
if(USB[i] instanceof Phone)
{
((Phone)USB[i]).call();//先向下转型,再调用Phone类中的call
}
}
接口多态传递
举例:
public class Test02 {
public static void main(String[] args) {
IB ib = new text();
IA ia = new text(); //此时就体现了接口多态传递
}
}
interface IA {
public void haha();
}
interface IB extends IA {
}
class text implements IB {
@Override
public void haha() {
System.out.println("haha");
}
}
上例中IA类型的变量ia能够指向text类的实例,但是text类只实现了IB接口。但是IB接口继承了IA接口,这个继承就体现了接口多态传递,如果没有这个继承,ia就不能指向text类的实例
内部类
分类:
定义在外部类的局部位置上(比如方法内):局部内部类,匿名内部类。
定义在外部类的成员位置上(比如属性,方法):成员内部类,静态内部类。
局部内部类
- 局部内部类是定义在方法中或者代码块中
- 作用域在这个方法体中或者代码块中
- 本质仍然是一个类,但是把他当成一个局部变量去使用
- 可以访问外部类的所有成员
如果外部类和局部内部类重名的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
举例
public class JuBu_ {
public static void main(String[] args) {
Outer out=new Outer();
out.fun1();
}
}
class Outer {
private int aa = 122;
public void fun1()
{
class Inner
{
public int bb_inner = 122;
public void fun2_inner()
{
System.out.println("外部类的aa为" + aa);
}
}
Inner inner=new Inner();
inner.fun2_inner();
}
}
匿名内部类
- 本质是类
- 该类没有名字
- 同时还是一个对象
基于接口实现匿名内部类:
就是在一个方法中或代码块中,写一个匿名内部类来实现这个接口(这个匿名内部类内部就和),并且只存在这一次,作用域结束后就消失
特点类似于局部内部类
此时编译类型为这个接口,运行类型为匿名内部类
举例:
package Inner_Class;
public class annoymous {
public static void main(String[] args) {
Outer1 out=new Outer1();
out.fun();
}
}
interface IN{
void cry();
}
class Outer1{
public int n=11;
public void fun()
{
IN dog=new IN(){ //此时实现了内部类
@Override
public void cry() {
System.out.println("汪汪");
}
};
dog.cry(); //调用这个匿名内部类的方法
}
}
基于类实现匿名内部类:
类似于基于接口
编译类型为基于的类,运行类型为匿名内部类
举例:
package Inner_Class;
public class annoymous2 {
public static void main(String[] args) {
Outer2 outer2=new Outer2();
outer2.fun();
}
}
class Outer2{
public int n=111;
public void fun(){
Father father = new Father("jack") { //基于类实现的匿名内部类
@Override
public void work() {
System.out.println("匿名内部类的" + name + "在工作");
}
};
father.work(); //调用匿名内部类的方法
}
}
class Father{
String name;
public Father(String name) {
this.name = name;
}
public void work()
{
System.out.println("在工作");
}
}
匿名内部类的用途:
当作参数传递:
public class annoymous3 {
public static void main(String[] args) {
f1(new IL() {
@Override
public void show()
{
System.out.println("showshow");
}
});
}
public static void f1(IL il){
il.show();
}
}
interface IL{
void show();
}
成员内部类
- 成员内部类是定义在外部类的成员位置,并且没有static修饰
- 可以直接访问外部类的所有成员
- 可以任意添加访问修饰符(public等),因为他的地位就是一个成员
举例:
public class annoymous5 {
public static void main(String[] args) {
Outer111 outer111=new Outer111();
outer111.fun();
}
}
class Outer111{
private int n=20;
class Inner000{
public void say()
{
System.out.println("n="+n);
}
}
public void fun()
{
Inner000 inner000=new Inner000();
inner000.say();
}
}
若要在其他外部类中使用这个内部类,方式如下
Outer111 outer111=new Outer111();
//外部其他类,使用成员内部类的方式
//第一种方式
Outer111.Inner000 inner000=outer111.new Inner000();
//第二种方式
Outer111.Inner000 inner0001=outer111.getInner();
第二种方式中需要在Outer11这个类中定义getInner这个方法
public Inner000 getInner()//返回内部类对象
{
return new Inner000();
}
静态内部类
- 类似于成员内部类
- 定义在外部类的成员位置,有static修饰
- 可以直接访问外部类的所有静态成员,包括私有的,但不能直接访问非静态成员
外部其他类访问静态内部类:
//方式一
Outer222 outer2221=new Outer222();
Outer222.Inner222 inner222 = new Outer222.Inner222();
//方式二
Outer222.Inner222 inner2221=outer2221.getInner();
举例:
public class annoymous6 {
public static void main(String[] args) {
Outer222 outer222 = new Outer222();
outer222.m1();
//外部其他类使用静态内部类
//方式一
Outer222 outer2221=new Outer222();
Outer222.Inner222 inner222 = new Outer222.Inner222();
//方式二
Outer222.Inner222 inner2221=outer2221.getInner();
}
}
class Outer222{
private static int n=100;
static class Inner222{
public void say(){
System.out.println(n);
}
}
public void m1()
{
Inner222 inner222=new Inner222();
inner222.say();
}
public Inner222 getInner(){
return new Inner222();
}
}