【Java基础概述-3】多态、实例\静态\局部\匿名内部类、Object类、Objects类、Date日期类

2023-12-29 10:47:17

目录

1.多态

1.1 多态的形式

1.2 多态的识别技巧

1.3 多态的前提

?1.4 多态的优略势(面试重点)

1.5 多态下的类型转换

2.内部类

??????? 2.1 内部的分类

????????2.2 静态内部类

??????? 2.3 实例内部类

??????? 2.4 局部内部类 (几乎不用)

??????? 2.5 匿名内部类 (重点)

3.Object类

4.Objects类

5.Date日期类


1.多态

??????? 众所周知,面向对象的三大特征为封装、继承、多态多态的概念是:同一类型的对象,在执行同一种行为的时候,在不同状态下表现出不同的行为特征。

????????1.1 多态的形式

????????父类类型 对象名称 = new 子类构造器。

????????接口? 对象名称 = new 实现类构造器。

????????1.2 多态的识别技巧

??????? 对于方法的调用,编译看左边,运行看右边

??????? 对于变量的调用,编译和运行都看左边。

????????1.3 多态的前提

??????? (1)必须存在父类类型的变量引用子类类型的对象。

??????? (2)必须存在继承关系和实现关系。

??????? (3)必须存在方法重写

案例:


public class PolymorphicDemo {
    public static void main(String[] args) {
        //父类类型>子类类型范围
        Animal dlam=new Cat();
        dlam.run();
        System.out.println(dlam.name);
        Animal td=new Dog();
        td.run();
        System.out.println(dlam.name);
    }
}
class Dog extends Animal{
    public String name="狗";
    @Override
    public void run() {
        System.out.println("狗跑的块~~");
    }
}

class Cat extends Animal{
    public String name="猫";
    @Override
    public void run(){
        System.out.println("猫跑的飞快~~");
    }
}
class Animal{
    public String name="动物";
    public void run(){
        System.out.println("动物跑!");
    }
}

?????????1.4 多态的优略势(面试重点)

??????????????? 优势:1.在多态形式下,右边对象可以实现组件化切换,业务功能也随之改变,便于扩展和维护。实现泪与泪之间的解耦。

????????????????? 2.在实际开发中,父类类型作为方法参数传入,传递给子类对象方法,可以传入一切子类对象进行方法调用,更能体现出多态的扩展性和便利性

??????? ????????缺点:1,多态形式下不能调用子类特有的功能。因为编译看左边,编译不能通过!!!

例子:

public class PolymorphicDemo {
    public static void main(String[] args) {
        Animal dog = new Dog();
        go(dog);
        Animal cat = new Cat();
        go(cat);
    }

    //第2条的解释
    //开发一个游戏 所有动物都可以进来比赛
    public static void go(Animal animal){
        System.out.println("开始。。");
        animal.run();
        System.out.println("结束。。");
    }

}

class Dog extends Animal {
    public String name="狗";
    @Override
    public void run() {
        System.out.println("狗跑的块~~");
    }
}

class Cat extends Animal {
    public String name="猫";
    @Override
    public void run(){
        System.out.println("猫跑的飞快~~");
    }
}
class Animal{
    public String name="动物";
    public void run(){
        System.out.println("动物跑!");
    }
}

????????1.5 多态下的类型转换

??????? 考虑一下在一个场景上,我们可能不需要用多态的形式了,但是之前用的就是多态形式,或者说以前没用多态,但是现在需要利用多态来进行业务代码的实现,应该如何进行类型转换:

??????? 规则:

??????? 1.小范围类型的变量或者值可以直接赋值给大范围类型的变量。

??????? 2.大范围类型的变量或者值必须强制转换给小范围类型的变量。

??????? 注意:

????? 1.? 父类类型的范围>子类类型的范围

、 ? 2.子类类型的变量或者值可以自动转换赋值给父类类型的变量

??????? 3.引用类型的自动转换不能解决多态的劣势。

例1:

public class PolymorphicDemo {
    public static void main(String[] args) {
        //1.引用类型的自动类型转换;小范围的对象赋值给大范围的对象
        Animal cat = new Cat();

        //2.引用类型的自动类型转换:小范围的变量赋值给大范围的变量
        Cat cat1 = new Cat();
        Animal c = cat1;
    }
}
class Dog extends Animal {
    public String name="狗";
    @Override
    public void run() {
        System.out.println("狗跑的块~~");
    }
}

class Cat extends Animal {
    public String name="猫";
    @Override
    public void run(){
        System.out.println("猫跑的飞快~~");
    }
}
class Animal{
    public String name="动物";
    public void run(){
        System.out.println("动物跑!");
    }
}

例2(强制转换):

public class PolymorphicDemo {
    public static void main(String[] args) {
        Animal dog = new Dog();
        dog.run();


        //动物类型转换成狗类型
        //大范围到小范围。
        Dog d = (Dog) dog;

        //看下强转能不能解决多态劣势
        d.eat();


//        Animal cat = new Cat();
        Animal cat = new Dog();

        System.out.println("----------------------");
        /*
        *
        * Exception in thread "main" java.lang.ClassCastException: _04多态_强制类型转换.Cat cannot be cast to _04多态_强制类型转换.Dog
	      at _04多态_强制类型转换.PolymorphicDemo.main(PolymorphicDemo.java:30)
        * */


        //避免下面这种情况可用instance:
        if(cat instanceof Cat){
            Cat cat1 = (Cat) cat;//这里把一个猫给了一直狗,编译类型不报错,运行阶段报错
            cat1.run();
        }else{
            Dog ddd = (Dog) cat;
            ddd.run();
        }
    }
}
class Dog extends Animal {
    public String name="狗";
    @Override
    public void run() {
        System.out.println("狗跑的块~~");
    }
    public void eat(){
        System.out.println("狗在吃东西~~");
    }
}

class Cat extends Animal {
    public String name="猫";
    @Override
    public void run(){
        System.out.println("猫跑的飞快~~");
    }
}
class Animal{
    public String name="动物";
    public void run(){
        System.out.println("动物跑!");
    }
}

注意:

??????? 虽然多态有一定的劣势,但是在开发中,它的优势是大于劣势的,在业务开发中,多态使用还是挺多的。

2.内部类

??????? 概念:定义在一个类里面的类称为内部类,它能提高更好的封装性,内部类有更多的权限修饰符,封装性有更多的控制。

??????? 2.1 内部的分类

  1. ? 静态内部类
  2. ? 实例内部类。(成员内部类)
  3. ? 局部内部类
  4. ? 匿名内部类(重点)

????????2.2 静态内部类

??????? 类有的成分它有,静态内部类属于外部类本身,只会加载一次

??????? 所以它的特点与外部类是完全一样的,只是位置在别人里面而已。

??????? 外部类:宿主

??????? 内部类:寄生

??????? 静态内部类的访问格式:

??????? 外部类名称.内部类名称

??????? 静态内部类创建对象的格式;

??????? 外部类名称.内部类名称 对象名称 = new 外部类名称.内部类名称。

??????? 注意:静态内部类可以访问外部类的静态成员,但是不能访问外部类的实例成员,外部类的静态成员只有一份,可以被共享,实例成员属于对象,直接访问不可以。

public class InnerClass {
    public static void main(String[] args) {
        Outter.Inner inner = new Outter.Inner();
        inner.setName("张三");
        inner.setAge(12);
        System.out.println(inner.getName());
        System.out.println(inner.getAge());
    }

}

class Outter{
    private static int age1=12;
    private String name1;

    public static class Inner{
    private String name;
    private int age;

        @Override
        public String toString() {
            return "Inner{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
        public void show(){
            System.out.println(age1);
//            System.out.println(name1);外部的实例成员不能访问,属于对象,都没实例化,如何拿外部的呢???
        }

        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;
        }
    }
}

??????? 2.3 实例内部类

??????? 无static修饰的内部类称为实例内部类,属于外部类的每一个对象一个,与对象一起加载。

??????? 实例内部类的特点:

??????? --实例内部类中不能定义静态成员。

??????? --可以定义常量。

?????? 创建对象格式:

??????? 外部类名称.内部类名称 对象名称 = new 外部类构造器.内部类构造器

??????? 实例内部类扩展:

??????? 实例内部类中可以访问外部类的静态成员也可以访问实例成员。

public class InnerDemo {
    public static void main(String[] args) {
        //实例内部类属于外部类对象,实例内部类属于外部类的对象。
        Outter.Inner inner = new Outter().new Inner();
        inner.setName("李四");
        System.out.println(inner);
    }
}

class Outter{
    private static int age;
    private String schoolName;
    public class Inner{

        private String name;
//        public static String schoolName="黑马";
//C:\Users\zlw\Desktop\Java\JavaPlus\Day03Demo\src\_08内部类_实例内部类\InnerDemo.java:29:30
//java: 内部类_08内部类_实例内部类.Outter.Inner中的静态声明非法
//  修饰符 'static' 仅允许在常量变量声明中使用
        //这里说明不能存在静态成员
        public static final String schoolName = "黑马";
        public void show(){
            System.out.println(age);
            System.out.println(schoolName);
        }
        @Override
        public String toString() {
            return "Inner{" +
                    "name='" + name + '\'' +
                    '}';
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}

??????? 2.4 局部内部类 (几乎不用)

??????? 概念:定义在方法中,构造器中,for循环中的内部类就是局部内部类

??????? 特点:

??????????????? -只能定义实例成员,不能定义静态成员

??????????????? -可以定义常量。

?????? 例子:

public class InnerClass {
    public static void main(String[] args) {
        class A{
            public void test(){
                System.out.println("这样写涉嫌装逼嫌疑");
            }

        }
        A a=new A();
    }
    public static void test(){
        class Animal{

        }
        class Cat extends Animal{

        }
    }
}

??????? 2.5 匿名内部类 (重点)

??????? 概述:没有名字的局部内部类,其实这里可以把它归结为局部内部类,因为方便区分,把有名字的局部内部类我们这里叫做局部内部类。

??????? 格式:

??????? new 类名|接口名|抽象类(形参){

????????//方法重写

????????}

??????? 匿名内部类的特点:

??????? 1.匿名内部类是一种没有名字的局部内部类。

??????? 2.匿名内部类一旦写出来,就立即创建一个匿名内部类的对象返回。

??????? 3.匿名内部类的对象的类型相当于当前new 那个类型的子类类型。

????????


public class Annoymity {
    public static void main(String[] args) {
        Animal a = new Animal() {
            @Override
            public void run() {
                System.out.println("猫跑得快");
            }
        };

        a.run();
        a.go();
    }

}

abstract class Animal{
    public abstract void run();
    public void go(){
        System.out.println("开始go");
    }
}

???????? 匿名内部类使用场景多数在于安卓开发,C/S开发,例如:

package _12匿名内部类使用场景;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/*
*
*
*
*
* */
public class Demo {
    public static void main(String[] args) {
        JFrame win =new JFrame("登录界面");
        win.setSize(400,300);
        win.setLocationRelativeTo(null);
        JButton btn = new JButton("开始登录");
        JPanel panel = new JPanel();
        panel.add(btn);
        win.add(panel);
        win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
//        btn.addActionListener(new ActionListener() {
//            @Override
//            public void actionPerformed(ActionEvent e) {
//                System.out.println("点了按钮");
//            }
//        });
        btn.addActionListener(s -> System.out.println("用户触发了登录"));
        win.setVisible(true);
    }
}

?

3.Object类

??????? 众所周知,任何类的祖宗类都是Object,Object中常用的两个方法:

??????? 1.public String toString():

??????? -默认返回当前对象所在堆内存信息

??????? -在我们进行输出的时候,实质上也是调用了toString()方法。

??????? -在开发中,我们输出变量的意义是为了看数据,所以父类中的toString()方法存在的意义就是被子类重写,以便输出对象内容信息!!!

??????? 例如:

public class Student {
    private String name;
    private int age;
    private char sex;

    public Student() {
    }

    public Student(String name, int age, char sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    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 char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;

    }


//重写了toString()方法
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                '}';
    }
}

public class ObjectToStringDemo {
    public static void main(String[] args) {
        Student student = new Student("张三",19,'男');
        student.toString();
        //直接调用toString方法返回的是对象在内存中的地址
        System.out.println(student);
        //直接输出对象名称,默认调用toString,所以tostring调用可以不写啊
    }



}

???????? 2.equal方法:

??????? public boolean equals():

??????? -默认是比较两个对象的地址是否相同,相同返回true,反之。

??????? -直接比较l两个对象的地址是否相同,完全可以用"=="代替。

??????? 所以equals存在的意义也是为了被子类继承,以便程序员可以定义自己的比较规则

????????


public class Student {
    private String name;
    private int age;
    private char sex;

    public Student() {
    }

    public Student(String name, int age, char sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    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 char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;

    }

    @Override
    public boolean equals(Object obj) {
    if(obj instanceof Student){
        Student stu =(Student) obj;
        if(this.name == stu.getName() &&
           this.age  == stu.getAge() &&
           this.sex  == stu.getSex()
        )return true;
        else{
            return false;
        }
    }
    return false;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                '}';
    }
}
public class ObjectEqualDemo {
    public static void main(String[] args) {
        Student student = new Student("张三",19,'男');
        Student student1 = new Student("张三",19,'男');
        System.out.println(student.equals(student1));
        System.out.println(student == student1);
    }



}

4.Objects类

??????? Objects类和Object之间还是继承的关系,也有equals方法,下图看出,其实还是调用了Object的equal 方法在底层,但是了,这里进行了空指针判断,如果为空,那么就直接是false,这也说明了比Object类更安全。

 Objects常用的两个方法,isNULL不是特别重要。:
1.public static boolean equals(){  
             --比较两个对象的地址 
--底层进行非空判断,从而避免空指针异常,更安全           
}

 2.public static boolean isNuLL(Object obj){
         询问obj是否是null
          }

public class Demo {
    public static void main(String[] args) {
        Student student = null;
        Student student1 = new Student();
        System.out.println(Objects.equals(student1,student));//正常,更安全,推荐使用
//        System.out.println(student.equals(student1));//会报空指针异常
        System.out.println(Objects.isNull(student));
    }
}

5.Date日期类

??????? Java是面向对象语言,会用一个类代表一个事务。

??????? Date类在Java中代表的是系统当前时刻时间对象。

??????? 包:java.util.Date

??????? 构造器(这里只说没有被淘汰的):

??????? -public Date();

??????? -public Date(long time):这里的long time是时间毫秒值,

?????? 方法:

??????? public long getTime():获取时间毫秒值。

看懂以下代码即可:

代码1:

    public static void main(String[] args) {
        //创建一个日期对象代表系统目前此刻信息
        Date date = new Date();
        System.out.println(date);

        //
        System.out.println(date.getTime());
    }

代码2(代码性能分析):

  public static void main(String[] args) {
        long time1 = new Date().getTime();
        for(int i=1;i<1000000;i++){
            System.out.println(i);
        }
        long time2 = new Date().getTime();
        System.out.println((double) (time2-time1)/1000+"s");
    }

代码三(有参构造器的使用):

   public static void main(String[] args) {
        //问121s以后的时间是多少
        Date date = new Date();
        long l = date.getTime() + 121 * 1000;
        Date date1 = new Date(l);
        System.out.println(date1);

    }

?

文章来源:https://blog.csdn.net/AiryCloud/article/details/135279902
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。