java学习第八天

java学习第八天

多态

一个类在编译的时候和运行时同一个方法可能会呈现出不同的状态。

比如:动物类都有一个会跑的方法,它的子类有一个乌龟,乌龟跑得慢。还有一个子类是狗类,狗跑得快

现在有一个动物类的对象,调用跑的方法,有可能跑得快,也可能跑得慢。

多态的形成条件

  1. 有继承关系,有多个子类,子类重写父类的方法
  2. 父类的类型定义的变量,用子类的实例给它赋值

多态的作用:

  1. 统一管理,无线适配或扩展。

    (例如:windows操作系统有打印功能,但是不知道用户要用什么样的打印机,所以他就规定一个方法。不同的打印机(针式、喷式、激光等)只要继承重写打印方法,就可以实现自动适配所有的打印机。

  • Animal.java

    public class Animal {
    
        public void run(){
            System.out.println("动物在跑");
        }
    }
    
    
  • Dog.java

    public class Dog extends Animal{
        @Override
        public void run() {
            System.out.println("狗跑得快");
        }
    }
    
  • Turtle

    public class Turtle extends Animal{
        @Override
        public void run() {
            System.out.println("乌龟跑得慢");
        }
    }
    
  • Test

    public class Test {
        public static void main(String[] args) {
            Animal animal = new Animal();
            animal.run();
    
            Dog dog = new Dog();
            dog.run();
    
            Turtle turtle = new Turtle();
            turtle.run();
    
            System.out.println("=========狗叫=====");
            Animal animal1 = dog;
            animal1.run();
    
            System.out.println("=========乌龟======");
            Animal animal2 = turtle;
            animal2.run();
        }
    }
    

    运行结果

    动物在跑
    狗跑得快
    动物在跑
    乌龟跑得慢
    =========狗叫=====
    狗跑得快
    =========乌龟======
    乌龟跑得慢
    

向上造型

父类 变量 = new 子类();

父类定义的变量,用子类的实例对象赋值。

注意:向上造型时,不能调用到子类中自己添加的方法。

System.out.println("=========狗叫=====");
Animal animal1 = dog;
animal1.run();

System.out.println("=========乌龟======");
Animal animal2 = turtle;
animal2.run();

向下造型

子类 变量 = (子类)父类的对象;

用父类的对象给子类的变量赋值,向下造型必须用强制类型转换。

向下造型分为几种情况:

  1. 直接new一个父类的对象,赋给子类的变量,运行时会抛异常(不允许)。
  2. 父类对象是通过子类的对象向上造型上去的实例,这种对象可以向下造型,但也要强制类型转换。子类的所有方法都可以访问到
  3. 与2一样的做法,但是换了同级的不同子类,如狗的子类对象,向下造型成乌龟,运行时也会抛出异常(不允许)。
 //1. 直接用父类创建的对象赋给子类变量,会抛出异常
        Dog cat = (Dog) new Animal();

        //2.把通过向上造型得到的父类对象赋给子类对象,可以调用继承自父类的方法,也可以子类自己的方法
        System.out.println("=====向下造型=====");
        Animal animal1 = dog;
        Dog dog1 = (Dog) animal1;
        dog1.run();
        dog1.eat();
        
		//3.一个父类的不同子类之间转换。
       Animal animal2 = new Dog();//Dog赋给animal2
       Turtle turtle1 = (Turtle) animal2;//animal2赋给turtle
       turtle1.run();
       turtle1.eat();

static修饰符(静态的)

static也是一种修饰符,他表示静态的意思,他可以修饰属性,方法,代码块

用static修饰的属性或方法称为静态的成员,它属于类的(不属于对象),所以可以直接使用。

静态的方法用于高频访问的方法(比如工具类的方法),方便调用

静态属性用于所有对象共享的属性(他只有一次,保存在类上的)

  • 静态的属性和方法
public class Parent {
    public static float pi = 3.14F;

    public static void area(float r){
        System.out.println(pi * r *r);;
    }
}
  • 静态的属性和方法可以直接用类名访问。
public class ParentTest {
    public static void main(String[] args) {
        System.out.println(Parent.pi);
        Parent.area(5);
    }
}

静态属性用于所有对象共享的属性。(只有一份,保存在类上)

public class Parent {
    public static float pi = 3.14F;
    public static int count;//属于类,只保存一次(共享的值)
    public int num;

    public static void area(float r){
        System.out.println(pi * r *r);;
    }

    public static float getPi() {
        return pi;
    }

    public static void setPi(float pi) {
        Parent.pi = pi;
    }

    public int getNum() {
        return num;
    }

    public int getCount(){
        return count;
    }

    public void setNum(int num) {
        count = num;
        this.num = num;
    }
}

测试结果

非静态成员是对象独有,互不干扰的

静态成员变量是所有对象共有的,任何一个对象改变了他,其他对象都能看到其改变后的结果。他不属于对象,属于类。

        Parent parent1 = new Parent();
        Parent parent2 = new Parent();

        parent1.setNum(5);//parent1对象设置为num = 5,count = 5
        parent2.setNum(8);//parent2对象设置为num = 8,count = 8

        System.out.println(parent1.getNum());//5
        System.out.println(parent1.getCount());
        System.out.println(parent2.getNum());//8
        System.out.println(parent2.getCount());
        System.out.println(Parent.count);//8
  • 静态的成员变量访问的条件

    1. 静态的成员变量在非静态的方法里可以访问

    2. 静态方法中才能访问静态成员变量

    3. 静态方法不能访问非静态属性

          public static void getData(){
              //System.out.println(num);非静态的方法不能访问非静态的属性
              System.out.println(count);//静态的方法才能访问静态的成员变量
          }
      

static修饰代码块

语法:

static{

​ //要执行的代码

}

静态代码块在类加载时执行(在构造方法之前),与它在类中的位置无关。

静态代码块一般用于初始化、条件准备或运行其他方法之前必须要先执行的代码

static {
        //在类加载的时候执行一次
        //在类中的位置无关,一般会放在成员变量和方法之间
        //会在构造方法之前执行
        System.out.println("静态代码块");
    }

jvm内存模型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k8lTEziS-1659152190637)(C:\Users\hanhan\Desktop\java基础笔记\java面向对象第8天\QQ图片20220729145017.jpg)]

Object对象及它的方法

Object类是所有类的父类,我们的类没有明确写继承Object(extends Object)他都会默认继承Object。

Object类有几个方法,所有的类都会继承这几个方法,有需要的时候也可以重写这些方法。

  • toString()

    如果一个对象直接用于显示,它默认会去调toString(),把返回的内容显示出来。

    对象的toString()方法默认返回类的全限定名再加上对象的地址(ID),这个信息没有太大的参高价值,所以我们经常重写toString()方法,返回属性的值。

    @Override
        public String toString() {
            return "Student{" +
                    "num=" + num +
                    ", name='" + name + '\'' +
                    '}';
        }
    
  • equals()和hashCode()

    hash是一种算法,根据一定的内容生成一个hash code值,用于判断两个内容是否一样的。

  • equals()方法判断两个对象是否内容相等,它依耐hashCode()方法。

     @Override
        public boolean equals(Object o) {
            //首先比较地址是否相等
            if (this == o) return true;
            //要比较的对象是否是null || 判断两个对象是否是同一个类创建的,如果不是,那就不相等。
            if (o == null || getClass() != o.getClass()) return false;
            //对要比对的内容强制转换,因为传过来的参数是Object。
            Student student = (Student) o;
            return num == student.num && Objects.equals(name, student.name);
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(num, name);
        }
    
    

    测试:

    Student student = new Student();
    
            student.setName("张三");
            student.setNum(1905555000);
            System.out.println(student);
    
            Student student1 = new Student();
            student1.setName("张三");
            student1.setNum(1905555000);
    
            System.out.println(student1);
            //对象用 == 比较,比较的是它们的地址
            System.out.println(student == student1);
    		//用equals判断两个对新疆,equals返回true,那么两个对象就相等
            System.out.println(student.equals(student1));
    
    
    /*        String s = student.toString();
            System.out.println(s);
            //直接打印对象,返回值就是toString()的返回内容
            //默认的toString()方法返回格式如下:com.HQYJ.ObjectDome.Student@4eec7777
            System.out.println(student);*/
        }
    

==与equals

基本类型判断是否相等==

应用(对象)类型用 == 判断,只是判断对象的地址,如果相等,说明是指向堆中的同一个对象。

逻辑上判断两个对象是否相等,需要用equals方法,往往需要重写equals。

注意:字符串的字面量赋值的时候,不会生成对象,而是存放在常量池,常量池中的字符是可以共享的。

System.out.println("=========双等和equals=====");
        short s = 65;
        int i = 65;
        char c = 65;
        System.out.println(s == i);
        System.out.println(i == c);
        //基本类型用 == 比较,它是比较的值,跟类型无关

        String str = new String("abc");
        String str2 = new String("abc");
        System.out.println(str == str2);//false
        System.out.println(str.equals(str2));//true

        String str3 = "xyz";
        String str4 = "xyz";
        //字面量赋值的字符串会保存在字符串常量池里。并不会创建一个对象。
        System.out.println(str3 == str4);//true
        System.out.println(str.equals(str4));//true
        
  • getClass()

    返回类的Class类型的对象。

    每一个类加载到方法区的时候都会生成一个Clas类型的对象,这个对象就是负责访问类的字节码。

  • finalize()

    gc(垃圾回收器),回收对象之前调用的一个方法。

  • notify 及 walt等方法

    这些方法是多线程使用的。

final

final意思是最终的,它也是修饰符,他可以修饰类,成员变量,方法。

  • 修饰属性

    1. 修饰成员变量时要赋值,static1 final修饰的成员变量就是常量
    2. 修饰局部变量,可以先定义在赋值
    3. 不管时修饰哪一种变量,只能被赋值一次,再也不能被修改
     //修饰成员变量
    //static加final修饰的成员变量,就是一个常量。
        public static final float pi = 3.14F;
        public static int count;//属于类,只保存一次(共享的值)
        public int num;
        //final的成员变量必须要初始化
        //final的变量不能再被赋值(值初始化之后就不能在改变)
        public final int flag = 0;
    
    //修饰局部变量
        public int getNum() {
            final int i;
            i = 2;
            //i = 3;只能赋值一次,不能重复赋值
            System.out.println(flag);
            System.out.println(i);
            return num;
        }
    
  • 修饰方法

  • final修饰的方法不能被重写

    public final void test(){
    
        }
    
  • 修饰类

    final修饰的类不能被继承

    public final class Parent {
    }
    

final、finallize、finally的区别

他们没有相同性,唯一相同的就是单词都是有final,很容易混淆,经常被作为面试题

  • final是一个修饰符(关键字),被final修饰的属性不能被修改,被final修饰的方法不能被重写,被final修饰的类不能被继承。

  • finallize是Object对象的一个方法,这个方法在垃圾回收之前会被调用。

  • finally是异常语句的一个分支,finally分支的代码一定会被执行。

    try{
        //可能会出异常的代码
    }catch(){
        //异常的处理代码
    }finally{
        //代码一定会被执行,一般用于资源的回收关闭
    }
    ``
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值