Java学习笔记-基础语法Ⅳ
多态:同一个对象,在不同时刻表现出来的不同形态
例如:
猫 cat = new 猫();
动物 animal = new 猫();
这里的猫在不同时刻表现出来不同的形态,这就是多态
多态的前提和体现:继承/实现方法、方法重写、父类引用指向子类对象
多态访问成员的特点:
- 成员变量:编译看左边,运行看左边
- 成员方法:编译看左边,运行看右边
// Animal类
public class Animal {
public int age = 30;
public void eat(){
System.out.println("动物吃东西");
}
}
// Cat类
public class Cat extends Animal{
public int age = 20;
public int weight = 10;
@Override
public void eat() {
System.out.println("猫吃东西");
}
public void play(){
System.out.println("猫在玩");
}
}
// 测试类
public class Demo {
public static void main(String[] args) {
Animal cat = new Cat();
// 对于变量,编译看左边,运行看左边
System.out.println(cat.age);
cat.age = 50;
// 但是如果在测试类中修改了变量值,那么还是会变化的,这个和方法重写又有点不一样
System.out.println(cat.age);
// System.out.println(cat.weight);
// 对于方法,编译看左边,运行看右边,因为重写了
cat.eat();
// 报错
// cat.play();
}
}
多态的好处:提高程序的扩展性,定义方法的时候使用父类型作为参数,使用时使用具体子类型的内容
// 动物类
public class Animal {
public void eat(){
System.out.println("动物吃东西");
}
}
// Cat类
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
// Dog类
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
// 操作方法
public class AnimalOperator {
/*
public void useAnimal(Cat cat){
cat.eat();
}
public void useAnimal(Dog dog){
dog.eat();
}
*/
public void useAnimal(Animal a){
a.eat();
}
}
public class Demo {
public static void main(String[] args) {
Cat c = new Cat();
AnimalOperator ao = new AnimalOperator();
ao.useAnimal(c);
Dog d = new Dog();
ao.useAnimal(d);
}
}
可以看到,使用多态,在写操作方法时,不用再一个个写,而是直接写父类,然后后面根据具体子类的内容进行调用
多态转型,从父类到了子类,并且可以既使用父类变量和方法,也可以使用子类变量和方法
// 父类
public class Animal {
public int age = 10;
public int sex = 20;
public void eat(){
System.out.println("动物吃东西");
}
public void show(){
System.out.println("Hello World!");
}
}
// 子类
public class Cat extends Animal{
public int age = 30;
public int name = 40;
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void playGame(){
System.out.println("猫在玩");
}
}
// 测试类
public class Demo {
public static void main(String[] args) {
Animal a = new Cat();
System.out.println(a.age);
System.out.println(a.sex);
a.eat();
a.show();
System.out.println("---------");
Cat cc = (Cat)a;
System.out.println(cc.sex);
System.out.println(cc.age);
System.out.println(cc.name);
cc.eat();
cc.playGame();
cc.show();
}
}
Java中,没有方法体的方法应该被定义为抽象方法,类中如果有抽象方法,那么该类必须为抽象类
public void XXX()
上述方法包含方法声明和方法体
抽象类不能直接创建对象
抽象类的特点:
- 抽象类和抽象方法必须使用abstract关键字修饰
- 抽象类中不一定有抽象方法(吃饱了撑的),有抽象方法的一定是抽象类
- 抽象类不能直接实例化,可以通过子类对象实例化(抽象类多态)
- 抽象类的子类要么重写抽象类中的所有抽象方法,要么是抽象类
抽象类可以有构造方法
// 动物类
public abstract class Animal {
private int age;
private String name;
public Animal(int age, String name) {
this.age = age;
this.name = name;
}
public Animal() {
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public abstract void eat();
}
// 猫类
public class Cat extends Animal{
public Cat(int age, String name) {
super(age, name);
}
public Cat() {
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
// 测试类
public class Demo {
public static void main(String[] args) {
Animal cat1 = new Cat();
cat1.setAge(18);
cat1.setName("小猫");
cat1.eat();
Animal cat2 = new Cat(17, "小小猫");
cat2.eat();
}
}
抽象类用自己的话小结:其他的和正常类没什么不同(主要是与接口对比),但是一般来说要有抽象方法
接口:一种公共的规范标准,只要符合规范标准,就都可以用。Java的接口体现在对行为的抽象
public interface 接口名{}
public class 类名 implements 接口名 {}
接口实例化:抽象类多态、接口多态,前提是有继承或者实现关系,有方法重写,且有父(类/接口)引用指向(子/接口)类对象
// 接口
public interface Jumpping {
public abstract void jump();
}
// 实现
public class Cat implements Jumpping{
@Override
public void jump() {
System.out.println("猫跳高");
}
}
// 测试类
public class Demo1 {
public static void main(String[] args) {
Jumpping j = new Cat();
j.jump();
}
}
public abstract class Dog implements Jumpping{
}
public class DogDemo extends Dog{
@Override
public void jump() {
System.out.println("狗跳高");
}
}
public class Demo2 {
public static void main(String[] args) {
Jumpping j = new DogDemo();
j.jump();
}
}
接口的成员特点:
- 成员变量:只能是常量,默认修饰符:public static final
- 构造方法:接口没有构造方法,接口主要对行为进行抽象,其子类默认继承Object类
- 成员方法:只能是抽象方法,默认修饰符:public abstract
下面将使用一个类
继承抽象类
并且实现接口
// 接口
public interface Inter {
void jumping();
// 验证调用,写在接口中的变量可以调用,但是不可以修改
int sex = 1;
}
// 抽象类
public abstract class Animal {
private String name;
private int age;
// 验证调用
public static int height = 10;
public Animal() {
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public abstract void eat();
}
// 猫类
public class Cat extends Animal implements Inter{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void jumping() {
System.out.println("猫跳高");
}
public Cat() {
}
public Cat(String name, int age) {
super(name, age);
}
}
// 测试类
public class Demo {
public static void main(String[] args) {
Cat cat1 = new Cat();
cat1.setAge(18);
cat1.setName("加菲");
cat1.eat();
cat1.jumping();
Cat cat2 = new Cat("布偶",16);
System.out.println(cat2.getAge()+" "+cat2.getName());
System.out.println(cat2.sex);
System.out.println(cat2.height);
}
}
类和接口的关系:
- 类和类:继承关系,只能单继承,但不能多继承
- 类和接口:类实现接口,可以单实现,也可以多实现
- 接口和接口:可以单继承,也可以多继承
抽象类和接口的区别:
- 成员区别:接口只有常量和抽象方法,抽象类几乎没什么限制
- 关系区别:接口可以实现多继承
- 设计理念:接口主要是行为上,抽象类主要是对象抽象,包括属性、行为
// 接口
public interface English {
void speak_english();
}
// 人的抽象类
public abstract class Person {
private int age;
private String name;
public Person() {
}
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public abstract void eat();
}
// 教练的抽象类
public abstract class Coach extends Person{
public abstract void teach();
public Coach() {
}
public Coach(int age, String name) {
super(age, name);
}
}
// 运动员抽象类
public abstract class Athlete extends Person{
public abstract void study();
public Athlete() {
}
public Athlete(int age, String name) {
super(age, name);
}
}
// 乒乓教练具体类
public class PinPonCoach extends Coach implements English{
public PinPonCoach() {
}
public PinPonCoach(int age, String name) {
super(age, name);
}
@Override
public void teach() {
System.out.println("乒乓教练教评判");
}
@Override
public void eat() {
System.out.println("乒乓教练吃肉");
}
@Override
public void speak_english() {
System.out.println("乒乓教练学英语");
}
}
// 篮球运动员具体类
public class BasketBallAthlete extends Athlete {
public BasketBallAthlete() {
}
public BasketBallAthlete(int age, String name) {
super(age, name);
}
@Override
public void eat() {
System.out.println("篮球运动员吃饭");
}
@Override
public void study() {
System.out.println("篮球运动员学篮球");
}
}
// 测试类
public class Demo {
public static void main(String[] args) {
PinPonCoach pc = new PinPonCoach();
pc.setAge(18);
pc.setName("lll");
System.out.println(pc.getAge()+" "+pc.getName());
pc.speak_english();
pc.eat();
pc.teach();
System.out.println("----------");
BasketBallAthlete bba = new BasketBallAthlete(18,"kkk");
bba.eat();
bba.study();
System.out.println(bba.getAge()+" "+bba.getName());
}
}
接口方法调用(抽象类)
// 接口
public interface Jumping {
void jump();
}
// 操作类
public class JumpOperator {
public void jump(Jumping j){
j.jump();
}
public Jumping getJump(){
Jumping j = new Cat();
return j;
}
}
// 用于接口实例化的猫类
public class Cat implements Jumping{
@Override
public void jump() {
System.out.println("猫跳高");
}
}
// 测试类
public class Demo {
public static void main(String[] args) {
JumpOperator jo = new JumpOperator();
Jumping j = new Cat();
jo.jump(j);
Jumping jump = jo.getJump();
jump.jump();
}
}
内部类:在类中定义一个类
内部类可以直接访问外部类的成员,包括私有,外部类若想访问内部类的成员,必须创建对象
在自己写代码的过程中,还遇到了一点问题,也记录下来
public class Outer {
private static int num = 10;
public static class Inner{
public void show(){
System.out.println("Hello");
System.out.println(num);
}
}
public void method(){
Inner i = new Inner();
i.show();
}
public static void main(String[] args) {
Inner i = new Inner();
i.show();
}
public int x = 1;
public int y = x+2;
// x = x+3;
public int age = 10+x;
Inner i = new Inner();
// 不能直接实例话后调用
// i.show();
}
想在类
中直接创建另一个类的对象
,然后调用方法,但是报错了,并且这时候试了下对变量进行运算也报错
查了下资料,发现类中只能出现5中内容:
属性、方法、构造方法、块以及内部类
但是初始化默认值时,可以进行一些运算操作(现在不是很懂这样的逻辑,先记录下来)
成员内部类,可以用private修饰,然后通过方法调用,这样外部使用的时候就看不到类中细节
成员内部类
public class Outer {
private int age = 20;
private class Inner{
public void show(){
System.out.println(age);
}
}
public void method(){
Inner i = new Inner();
System.out.println(age);
}
}
public class Demo {
public static void main(String[] args) {
// Outer.Inner oi = new Outer().new Inner();
// oi.show();
Outer o = new Outer();
o.method();
}
}
局部变量前面不加修饰符
方法内部类
public class Outer {
private int age = 18;
public void method(){
// 局部变量不加修饰符
class Inner{
public void show() {
String name = "Hello";
System.out.println(age);
}
}
Inner i = new Inner();
i.show();
}
}
public class Demo {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
匿名内部类
public class Outer {
public void show1() {
/*
new Inter(){
@Override
public void show() {
super.show();
// System.out.println("World");
}
}.show();
*/
Inter i = new Inter(){
@Override
public void show() {
super.show();
}
};
i.show();
}
}
public class Inter {
public void show(){
System.out.println("Hello");
}
}
public class Demo {
public static void main(String[] args) {
Outer o = new Outer();
o.show1();
}
}
匿名内部类在实际开发中的应用:
// 接口
public interface Inter {
void jump();
}
// 方法
public class InterImplements {
public void show(Inter i){
i.jump();
}
}
// 测试
public class Demo {
public static void main(String[] args) {
InterImplements ii = new InterImplements();
ii.show(new Inter() {
@Override
public void jump() {
System.out.println("狗跳高");
}
});
}
}
到此,Java学习中的基本编程思想告一段落,下面将是常用API