代码块 继承 多态

简介: 代码块 继承 多态

                                     世事漫随流水,算来一梦浮生。

                                                                                                                        ------DJ懒洋洋

一:代码块

1):普通代码块

  普通代码块:定义在方法中的代码块。

public class test7{
    public static void main(String[] args) {
        {
            int  x=10;
            System.out.println(x++);
        }
    }
}

2):构造代码块

 构造代码块:一般放在类中的代码块

public class  Student{
    public String name;
    public int age;
    {
        this. name="李华";
        this.age=18;
    }
    public static void main(String[] args) {
        Student student=new Student();
        System.out.println(student.name);
        System.out.println(student.age);
    }
}

即作用:对成员变量进行初始化。

3:静态代码块

静态代码块:即由static修饰的代码块,不加修饰符。一般用来对静态成员变量进行初始化。

public class  Student{
    public String name;
    public int age;
    public static String classRoom;
    {
        this. name="李华";
        this.age=18;
    }
    static{
        classRoom="301";
    }
    public static void main(String[] args) {
        System.out.println(Student.classRoom);
    }
}

那么,静态代码块,构造代码块,放在一起会执行哪一个?

public class  Student{
    public String name;
    public int age;
    public static String classRoom;
    {
        this. name="李华";
        this.age=18;
        System.out.println("hehehe");
    }
    static{
        classRoom="301";
        System.out.println("hahah");
    }
    public static void main(String[] args) {
        System.out.println(new Student().name);
        System.out.println(new Student().age);
        System.out.println(Student.classRoom);
    }
}

代码运行结果如下:

 

由上述代码可知,我们创建了两次对象,且这两次对象我们对他们的姓名和年龄利用构造代码块进行,在main函数中,我们先创建了两次对象,来调用其属性值,再通过类名调用其静态变量,通过打印得知,无论main函数先运行哪个,静态代码块总是先执行,再执行构造代码块,且静态代码块只执行一次。

二:继承

1): 继承:关键字

如下图所示:

  我们可以抽出cat和dog共有的属性和成员行为,将其放到Animal类中。即cat和dog继承于Animal类。此时Animal为cat和dog的父类,cat和dog为Animal的子类。

官方术语:对共性进行所谓的抽取,把抽取的共性放到父类中,达到代码的复用。java常见的继承方式如下图所示:

 

public class Animal {
    public String  name;
    public int age;
    public Animal() {
    }
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public Animal setName(String name) {
        this.name = name;
        return this;
    }
    public int getAge() {
        return age;
    }
    public Animal setAge(int age) {
        this.age = age;
        return this;
    }
    public void eat(){
        System.out.println("吃东西");
    }
}
class Dog extends Animal{
    public Dog(){
       super();
    }
    public String id;
    public Dog(String name,int age,String id){
        super(name,age);
        this.id=id;
    }
    public void eat(){
        System.out.println(this.name+"在吃骨头");
    }
}
class Cat extends  Animal{
    public Cat(){
    }
    public Cat(String name,int age){
       super(name,age);
    }
    public void eat(){
        System.out.println(this.name+"在吃鱼");
    }
    public static void main(String[] args) {
        Dog dog=new Dog("小旺旺",18,"1");
        dog.eat();
        Cat  cat=new Cat("小花",19);
        cat.eat();
    }
}

运行结果:

 

如上述代码所示,我们实现了继承这一关系。但仍有很多注意的小点。

注意:

  1:super关键字的使用,用来访问父类的成员变量和成员行为。

   代码演示:

   父类:

public void play(){
     System.out.println("好好玩耍");
   }

子类:

   

public Dog(){
       super();
       super.play();
    }

注意:

  1:父类的空参构造在子类中是默认的,即使不写,idea也会自动添加。

  2:如果父类成员变量和子类成员变量的变量名重合时,优先访问子类的成员变量,非要访问父类的成员变量,则需要super关键字来进行访问。那么,继承了父类的成员变量,子类完成实参或者空参构造前,必须先给父类进行构造。该结构图是什么样的?

2):final关键字

   final关键字,修饰类不能被继承,修饰常量不能被更改。

以如下代码为例:当final修饰Animal这个类时,狗类进行继承,发现编译器会报错。印证了上面的一点,由final修饰的类不能被继承。

final public class Animal {
    public String name;
    public  int age;
    public Animal() {
    }
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public Animal setName(String name) {
        this.name = name;
        return this;
    }
    public int getAge() {
        return age;
    }
    public Animal setAge(int age) {
        this.age = age;
        return this;
    }
}
class Dog extends Animal{
}

以如下代码为例,发现由final修饰的变量会变为常量,且不能被修改。

public class Main {
    public static void main(String[] args) {
       final int a=10;
       a=120;
    }
}

结果如下:

三: 多态

1):各个代码块的执行顺序:

1:当父类的静态代码块,子类的静态代码块,父类的实例代码块,子类的实例代码块,父类的构造代码块,子类的构造代码块放在一起,执行顺序是怎样的?

以如下代码为例:

public class Person {
    private String name;
    private int age;
    public static String  livinghouse;
    //父类的静态代码块
    static{
        livinghouse="301";
        System.out.println("父类的静态代码块");
    }
    {
        System.out.println("父类的构造块");
    }
    public Person() {
    }
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public Person setName(String name) {
        this.name = name;
        return this;
    }
    public int getAge() {
        return age;
    }
    public Person setAge(int age) {
        this.age = age;
        return this;
    }
  public static String eat(){
      return "地球人都吃饭";
  }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
class  Student1 extends Person{
    public String id;
    public Student1() {
        super();
    }
    public Student1(String name, int age,String id) {
        super(name, age);
        this.id=id;
    }
    static{
        System.out.println("我是子类静态代码块");
    }
    {
        System.out.println("我是子类构造块");
    }
    public String getId() {
        return id;
    }
    public Student1 setId(String id) {
        this.id = id;
        return this;
    }
    @Override
    public String toString() {
        return "Student1{" +
                "id='" + id + '\'' +
                '}';
    }
}
class test1{
    public static void main(String[] args) {
        Person person=new Person("小李",18);
        System.out.println(person);
        System.out.println(Person.livinghouse);
        System.out.println(Person.eat());
        System.out.println("===============");
        Student1 student=new Student1("小花",19,"10");
        System.out.println(student);
        System.out.println("===============");
        Student1 student1=new Student1("小明",20,"11");
        System.out.println(student1);
    }
}

以上述代码为例,我们来看执行顺序:

 

如上述代码运行结果如图:

1:先执行父类的静态代码块,再执行父类的构造块,再执行父类的实例化对象,再执行子类的静态代码块,父类的构造块,子类的构造块,再执行子类的实例化对象,且我们在创建第二个学生对象的同时,发现父类的静态代码块和子类的静态代码块只执行一次。

如上:静态代码块>构造块>实例化对象,父类的执行顺序>子类的执行顺序。

2):多态

1: 概念:同一件事情,发生在不同对象身上,会产生不同的效果。在实现多态之前,我们得先了解什么是重写

重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变

1:方法名相同

2:参数列表相同

3:返回值相同。

//父类的play方法
public void play(){
      System.out.println("好好玩");
    }
//子类对父类的play方法进行重写
public void play(){
        System.out.println("开心的玩耍");
    }

哪些情况不能被重写?

1:被priavte修饰的方法不能被重写,因为private是私有化,且只能在本来中使用。

2:被static修饰的方法不能重写,因为static修饰的方法为静态方法,只能通过类名来调用。

3:子类的访问权限修饰符>=父类的权限修饰符

4:重写的方法所在的类不能被final修饰,即被final修饰的父类不能被子类继承。

5:父类的实参构造和空参构造不能被重写。

2):向上转型

如上图所示:即子类向父类进行转型,由小范围往大范围转,且子类必须对父类的方法进行重写,这就叫多态

代码如下:我们创建一个Animal的父类,创建猫和狗的子类来继承Animal的父类。

public class Animal {
   private String name;
   private int age;
    public Animal() {
    }
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public Animal setName(String name) {
        this.name = name;
        return this;
    }
    public int getAge() {
        return age;
    }
    public Animal setAge(int age) {
        this.age = age;
        return this;
    }
    public void eat(){
        System.out.println("好好吃饭");
    }
}
class Dog extends Animal{
    String typeFood;
    public Dog() {
        super();
    }
    public Dog(String name, int age,String typefood) {
        super(name, age);
        this.typeFood=typefood;
    }
    @Override
    public void eat(){
        System.out.println(super.getName()+"在吃:"+this.typeFood);
    }
}
class Cat extends Animal{
    String typefood;
    public Cat() {
        super();
    }
    public Cat(String name, int age,String typefood) {
        super(name, age);
        this.typefood=typefood;
    }
    public void eat(){
        System.out.println("可爱的"+super.getName()+"在吃:"+this.typefood);
    }
}
class test2{
    public static void eat(Animal animal){
        animal.eat();
    }
    public static void main(String[] args) {
        eat(new Dog("小狗",12,"骨头"));
        eat(new Cat("小花",11,"猫粮"));
    }
}

运行结果:

3):向下转型

代码如下:且需要强转,且不安全。

 

Dog dog=(Dog)new Animal();

今天就到这了,感谢各位大佬的捧场!!!欢迎各位大佬批评指正。

相关文章
|
7月前
|
C#
初识继承和多态
初识继承和多态
|
2月前
多态和动态绑定的区别是什么?
【10月更文挑战第14天】多态和动态绑定是面向对象编程中两个重要的概念,但它们有着不同的含义和作用。
26 2
|
7月前
|
存储 设计模式 编译器
【C++】继承和多态常见的问题
【C++】继承和多态常见的问题
|
7月前
|
安全 Java 编译器
继承与多态
继承与多态
|
编译器 程序员 C++
【C++】继承和多态
【C++】继承和多态
441 3
|
Java
类的继承多态
类的继承多态
80 0
总结继承和多态的一些问题
本人学习了多态和继承后的一些问题,解答出来并总结,有些是容易搞混的概念。
总结继承和多态的一些问题
|
Java 编译器 程序员
继承和多态
继承和多态
继承与多态(2)
继承与多态(2)
107 0
继承与多态(2)