多态,内部类
一。接口作为方法参数, 接口作为返回值:
具体使用的都是接口的实现类对象
1.创建接口
public interface Interface1 {
void method1();
void method2();
}
2.创建实现类
public class InterfaceImpl implements Interface1{
@Override
public void method1() {
System.out.println("实现类重写方法1");
}
@Override
public void method2() {
System.out.println("实现类重写方法2");
}
}
3. 接口类型作为方法参数,返回值为接口类型
public class DemoIt {
//接口类型返回值的方法
public Interface1 it(Interface1 a){
//此处等于默认有 Interface a=new InterfaceImpl();
// a 调用的是哪个方法, 具体看传入的对象是哪个实现类
a.method1();
a.method2();
System.out.println("结束");
/*相当于创建了一个接口的实现类对象, 向上造型为接口类型
Interface a=new InterfaceImpl();
接口类型的对象返回return a;*/
return a;//等于return new InterfaceImpl();
}
}
4.主函数调用
public class Main {
public static void main(String [] ages){
DemoIt demo=new DemoIt();
//接口无法创造对象,所以用实现类创造对象
InterfaceImpl a=new InterfaceImpl();
//实现类对象作为参数给It方法中的接口类型参数做参数
demo.it(a);
InterfaceImpl a2=new InterfaceImpl();
//调用方法并且接收返回值时,由于 xx.it(xx)返回值是Interface类型
Interface1 re=demo.it(a2);
}
}
二。多态
①
1.父类
public class Fu {
int age = 10;
int num = 100;
public void m1() {
System.out.println("Fu m1方法");
}
public void m2() {
System.out.println("Fu m2方法");
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
}
2.子类
public class Zi extends Fu {
// 和父类中同名的成员变量
int age = 20;
// 和父类中不同的成员变量 - 子类自己单独声明的
int score = 150;
// 额外继承了父类中的num变量
// 重写父类中的m1方法
public void m1() {
System.out.println("Zi m1方法");
}
// 继承了父类的m2方法
// 子类自己的方法 m3
public void m3() {
System.out.println("Zi m3方法");
}
@Override
public int getAge() {
return age;
}
}
3.父类型引用 指向 子类型对象
Fu f = new Zi();
// 无关类 不叫 向上造型, 写法错误
// Fu f1 = new Self();
/*
以下两种不叫多态
Fu f1 = new Fu();
Zi zi = new Zi();
*/
4.多态表现方面1:
成员变量的调用, 子父类中拥有相同的成员变量并且都有一对get/set方法
如果通过引用直接调用成员变量 f.age, 看引用变量f左边类型来调用
通过方法调用成员变量f.getAge(), 看引用变量右边类型来调用
public class Main1 {
public static void main(String[] args) {
Fu f = new Zi();
System.out.println(f.age); // 10
// 子类中重写了getAge()方法, 得到20
// 子类中没有重写getAge()方法, 得到10
System.out.println(f.getAge()); // 20
System.out.println(f.num);
// Fu类中没有声明score变量, 不能直接调用
// System.out.println(f.score);
// int a = (int)3.14; double d = 3;
// 向下转换类型
Zi zi = (Zi) f;
System.out.println(zi.score);
}
}
5. 多态的表现方面2: 成员方法的调用
最终调用的是哪个方法:优先调用子类重写过的,子类中如果没有重写,
就调用父类的方法
public class Main2 {
public static void main(String[] args) {
Fu f = new Zi();
f.m1();
// m3没有在Fu中声明, 所以不能直接调用
// f.m3();
// 如果想用子类自己的方法, 需要强制转换
Zi zi = (Zi) f;
zi.m3();
}
}
②多态: Animal a1 = new Cat();
Animal a2 = new Dog();
1.抽象父类,抽象方法
public abstract class Animal {
public abstract void eat();
}
2.子类
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("吃鱼");
}
public void catchMouse(){
System.out.println("抓老鼠");
}
}
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("吃骨头");
}
public void watchHouse(){
System.out.println("看门");
}
}
3。多态主要用处是Animal作为参数,可以传递多种类型的对象,以Animal抽象类为返回值的那个方法可以返回多种不同种类的对象
public class Test {
public static void main(String [] ages){
//向上造型:父类型引用指向子类型对象
Animal m1=new Cat();
// m1.eat();
Animal m2=new Dog();
// m2.eat();
/*
Cat c=new Cat();
Dog d=new Dog();
c.catchMouse();
d.watchHouse();
*/
//showCatEat(c);
//showDogEat(d);
showAnimalEat(m1);
showAnimalEat(m2);
}
public static Animal salepet(){//以Animal抽象类为返回值,这个方法可以返回多种不同
return null;
}
//Animal作为参数,可以传递多种类型的对象
public static void showAnimalEat(Animal a){
if(a instanceof Cat){//instanceof用来判断a是否是new出的Cat
Cat cat=(Cat) a;
cat.catchMouse();
}
else if( a instanceof Dog){
Dog dog=(Dog) a;//向下转型
dog.watchHouse();
}
a.eat();
}
}
三。内部类: 类中写个类
种类: 成员内部类,静态内部类,局部内部类[匿名内部类]
1.成员内部类:权限 public,protected,(default),private
使用:
内部类中, 可以随意使用外部类成员
外部类中, 使用内部类成员时需要创建内部类对象
无关类中, 使用内部类成员
1.间接调用, 在外部类方法中调用内部类方法
main方法中, 调用外部类方法
2.直接调用, 需要创建内部类对象
外部类.内部类 a = new 外部类().new 内部类();
内部类和外部类有同名成员变量
外部类的成员变量: 外部类.this.变量
内部类的成员变量: this.变量
// 外部类
public class Body {
public void walk() {
System.out.println("身体在行走");
// 外部类中, 直接创建内部类对象
Heart heart = new Heart();
heart.beat();
// 外部类中使用内部类成员变量, 需要内部类对象
System.out.println(heart.num);
System.out.println(a); // 外部类的a
}
private int a = 10;
// 成员内部类: 成分和外部类一样
public class Heart {
int num;
int a = 20;
public void beat() {
int a = 30;
// 内部类中可以直接使用外部类成员
System.out.println("心脏跳动" + a++);
// 内部类的成员a
System.out.println(this.a);
// 外部类的成员变量a
System.out.println(Body.this.a);
}
}
}
public class Main {
public static void main(String[] args) {
// 在无关类中 使用Body的内部类Heart
Body body = new Body();
// 间接调用内部类
body.walk();
// 直接调用内部类, 通过外部类对象创建内部类对象
Body.Heart heart = body.new Heart();//与//Body.Heart heart = new Body().new Heart();相同
heart.beat();
}
}
2.局部变量a:
局部内部类中使用局部内部变量必须为final
public class Outer {
private int b = 20;
public void m1() {
// 和局部内部类同方法的局部变量 a
/*final */int a = 10;
class Inner {
public void innerM1() {
int c = 0;
System.out.println("局部内部类m1" + a);
System.out.println("成员变量: " + b);
}
}
Inner i = new Inner();
i.innerM1();
//a ++; final 不可变
b ++;
}
}
3.局部内部类: 在方法内部定义类, 只在方法中有效
在局部内部类中, 使用局部变量, 必须是final的
JDK8 后, 局部变量事实上没有发生改变, 那么final可以省略
一次性的类, 只能用一次
不能使用权限修饰符
局部内部类, 需要类只使用一次, 优化 -> 匿名内部类
public interface MyInterfaceA {
void methodAbs1();
void methodAbs2();
}
// 只想用一次, 只想在Outer类中的m1方法中使用
public class MyInterfaceImpl implements MyInterfaceA {
@Override
public void methodAbs1() {
System.out.println("方法1");
}
@Override
public void methodAbs2() {
System.out.println("方法2");
}
}
public class Outer {
public void m1() {
class InnerImpl implements MyInterfaceA {
@Override
public void methodAbs1() {
System.out.println("内部类实现1");
}
@Override
public void methodAbs2() {
System.out.println("内部类实现2");
}
}
// 使用接口的方法, 创建接口的实现类
InnerImpl impl = new InnerImpl();
impl.methodAbs1();
impl.methodAbs2();
}
}
4.匿名内部类: 继承抽象类或实现接口
语法: new 接口/抽象类() {
int a;
// 实现的所有抽象方法
}
匿名内部类, 只能用一次, new一个对象
匿名对象, 只能使用一次, 只能调用一次方法
注意: 匿名内部类 和 匿名对象 不是一回事 ! ! !
public interface MyInterfaceA {
void methodAbs1();
void methodAbs2();
}
public class Outer {
public static void main(String[] args) {
// 匿名内部类本质: 实现接口或者继承抽象类
/*
new MyInterfaceA(){..}
new: 创建MyInterfaceA 的实现类对象
MyInterfaceA: 想要实现的接口, 抽象类
{..}: 真正的类, 没有名字
弊端: 只能用一次, 只能创建一次对象
*/
MyInterfaceA impl = new MyInterfaceA() {
int a = 10;
@Override
public void methodAbs1() {
System.out.println("内部类实现1" + a++);
}
@Override
public void methodAbs2() {
System.out.println("内部类实现2");
}
};
impl.methodAbs1();
impl.methodAbs2();
new MyInterfaceA() {
int a = 10;
@Override
public void methodAbs1() {
System.out.println("内部类实现1" + a++);
}
@Override
public void methodAbs2() {
System.out.println("内部类实现2");
}
}.methodAbs1();
// 匿名对象, 只能调用一次方法
new Outer().getClass();
new Outer().hashCode();
}
}
- 静态内部类: 对比 成员内部类 => 静态方法 和 成员方法
public class Outer {
// 成员方法
public void m1() {
new Inner();
new InnerField();
}
// 静态方法
public static void m2() {
new Inner();
// new InnerField();
}
// 成员内部类
public class InnerField {
}
// 外部类的成员变量
int a = 10;
// 外部类的静态成员变量
static int b = 20;
// 静态内部类, 属于类的
public static class Inner {
public void m3() {
// 不能使用非静态成员
// System.out.println(a);
System.out.println(b);
}
}
}
import com.zzxx.demo8.Outer.Inner;
public class Main {
public static void main(String[] args) {
// 成员内部类创建对象, 需要外部类对象
Outer.InnerField inner1 = new Outer().new InnerField();
// 静态内部类创建对象
Outer.Inner inner2 = new Outer.Inner();
// 简化 -> 需要import
Inner inner3 = new Outer.Inner();
}
}
本文地址:https://blog.csdn.net/LDRaaa/article/details/107370083
上一篇: 荐 Volatile你真的懂了吗?
下一篇: RabbitMQ-RPC案例