day08-fire
<h1 id="重写多态类型转换其他">重写/多态/类型转换/其他</h1><h4 id="重写">重写</h4>
<h6 id="子类和父类拥有同名非静态static方法时会发生重写">子类和父类拥有同名非静态(static)方法时会发生重写</h6>
<p><em><strong>父类的引用可以指向子类(和多态有关)</strong></em></p>
<p><strong><mark>B类</mark></strong></p>
<pre><code class="language-java">package com.example.demo.oop.obj;
public class B {
public void a(){
System.out.println("B=>a()");
}
}
</code></pre>
<p><strong><mark>A类</mark></strong></p>
<pre><code class="language-java">package com.example.demo.oop.obj;
public class A extends B {
@override//注解:有功能的注释
public void a(){
System.out.println("A=>a()");
}
}
</code></pre>
<p><strong><mark>Test</mark></strong> <strong>发生了重写了</strong></p>
<pre><code class="language-java">package com.example.demo.oop.obj;
public class Demo03 {
public void main(String[] args) {
A a=new A();
B b=new A();
a.a();//A=>a()
b.a();//A=>a()
}
}
</code></pre>
<h5 id="static的进一步类和对象">static的进一步:类和对象</h5>
<p>当A,B类里的同名方法是static的时候,这时候输出结果就是<mark>A=>a()和B=>a()</mark>,这是因为static是<mark>类级别的</mark>,内存加载时会直接加载在堆空间。那么谁(<mark>A或B声明</mark>)就会指向谁的方法,这时候就没有发生<strong>重写</strong>。只有当其方法为<strong>非静态</strong>方法是,即<mark>对象级别的</mark>,那么<mark>new</mark>时就根据类名来确定方法。(和下面结合一下重写理解可能会更好)</p>
<h4 id="关于重写和多态的问题">关于重写和多态的问题</h4>
<p>这里有个问题:<strong>父类的对象可以指向子类</strong>:</p>
<blockquote>
<p>这是 Java 中<strong>多态(Polymorphism)</strong> 的核心体现之一,语法上称为 “向上转型(Upcasting</p>
<p>本质是 “<strong>子类是父类的一种特殊形式</strong>”(比如 “狗是动物的一种”),符合 “is-a” 关系 —— 既然 Dog 属于 Animal 范畴,用 Animal 类型的变量来 “指代” Dog 对象,逻辑上完全成立</p>
</blockquote>
<p>Q:<em>A是B的子类,可以B a=new A(),但是不能A a =new B()对吧?就是可以说子像父,但是不能说父像子一样?</em></p>
<p>A:<strong>核心逻辑就是 “is-a” 关系的单向性</strong>,<strong>父类引用可以指向子类对象,子类引用不能指向父类对象</strong></p>
<p><strong><mark>关于调用成员限制:</mark></strong>只能调用父类中声明的成员</p>
<p>父类引用指向子类对象后,<strong>只能访问父类中定义的方法 / 属性,无法直接访问子类特有的方法 / 属性</strong>(除非通过 “向下转型” 强制转换类型)</p>
<p>简言之:<strong>父类引用能 “装” 子类对象,但只能用父类有的 “功能”</strong>。</p>
<h4 id="final--static">final & static</h4>
<p><strong>final确保工具类/方法不被修改,而static确定了其属于对象还是类级别</strong></p>
<p>**<mark>summary:</mark> ** <strong>重写</strong>:</p>
<ol>
<li>必须有<strong>继承关系</strong></li>
<li>方法名要一致</li>
<li>修饰符可以扩大,但是不能缩小 private<default<protected<public</li>
<li>重写可能会抛出异常:范围可以被缩小,但是不能扩大(精细化,错误有粗略到详细)如:ClassNotFoundException --> Exception</li>
</ol>
<p><strong>为什么需要重写:</strong></p>
<ol>
<li>从一般出发,<strong>需求冲突,即子类需要的方法或者其他父类不能满足</strong></li>
</ol>
<p><strong>快捷键:<mark>alt+ins</mark>可以重写方法,构造方法等等</strong></p>
<h4 id="多态">多态</h4>
<blockquote>
<p>[!IMPORTANT]</p>
<p><strong>多态的核心:“编译看左边,运行看右边”</strong></p>
<p>在编译阶段,只看父类中是否有该方法,在运行时会调用实际指向的对象也就是子类,这就是多态的<strong>核心</strong></p>
</blockquote>
<p><strong>对于子类A和父类B和基类Object</strong></p>
<pre><code class="language-java">//一个对象的实际类型是一定的
//new A()
//new B()
//但是引用类型就不一定了,父类可以指向子类
//但是可以和(type)强制转换,把父类的对象引用强制转换为子类。这样也可以调用子类的方法
/*
多态注意事项:
1.多态是方法的多态
2.类型转换是需要有继承关系的(转换异常:ClassCastException)
3.存在:
继承关系
方法重写
父类的引用指向子类
**/
</code></pre>
<p>我的粗浅理解:从内存分配来说,在编译时有标识身份的类来说明,编译查看声明类是否有该方法,没有就直接报错。在运行时,根据<strong>关键字new</strong>创建的空间来确定引用实际指向的方法。如果子类没有就向去父类里面找。</p>
<p><strong>方法加载一次,跟着类走,属性跟着对象走,每个对象一份。只是非static的方法依赖于对象来调用而已</strong></p>
<p><strong>子类的加载依赖于父类的加载,先父后子嘛</strong></p>
<h2 id="instanceof-和类型转换">instanceOf 和类型转换</h2>
<p><strong>x instanceOf y</strong>:</p>
<ol>
<li>x和y有继承关系才会编译通过</li>
<li>真假值和x实例是不是y的子代</li>
</ol>
<p><strong>类型转换</strong>:<mark>高转低要强转</mark></p>
<ol>
<li>
<p>父类的引用指向子类的对象</p>
</li>
<li>
<p>如果调用身份不符的方法的话就无法调用,所以需要类型转换</p>
</li>
<li>
<pre><code class="language-java">B obj = new A()//A里有自己的方法go()
((A) obj).go()//这样强转身份就可以调用子类的方法了
</code></pre>
</li>
<li>
<p>子类转换为父类可能会丢失一些方法</p>
</li>
</ol>
<h2 id="static">static</h2>
<pre><code class="language-java">{
System.out.println("匿名代码块,用于复初值,先于构造方法,且没new一个实例都会再运行一次")
}
static{
System.out.println("static代码块,于类同时,最先执行且只执行一次,因为是类级别的,然后才是main方法")
}
</code></pre>
<p><strong>类加载和初始化</strong></p>
<p><strong>jvm先找到类的main方法,但是在<mark>执行main方法前必须对类进行初始化</mark>,包括了static代码块</strong></p>
<p><strong>只有初始化类后才执行main方法,这就是为什么先输出static块再输出main的原因</strong></p>
<p><strong>静态导入包 import static Java.lang.Math.max</strong></p>
<p>😘</p><br><br>
来源:https://www.cnblogs.com/billmu/p/19074498
頁:
[1]