java基础-多态性
1.体现:父类的引用指向子类的对象,应用在抽象类和接口上;
java引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明时使用的类型决定,运行时类型由赋给该变量的对象决定。编译时看左边,运行时看右边;
也就是说,多态情况下,我们只能调用父类中存在的方法,然而实际运行时,运行的是子类中的方法;
public class Person {String name;int age;public void eat(){System.out.println("人吃饭");}public void walk(){System.out.println("人走路");} }
public class Man extends Person{boolean isSmoking;public void earnMoney(){System.out.println("男人负责挣钱");}public void eat(){System.out.println("大吃大喝");}public void walk(){System.out.println("大摇大摆");} }
public class Women extends Person{boolean isBeauty;public void shopping(){System.out.println("女人负责购物");}public void eat(){System.out.println("小吃小喝");}public void walk(){System.out.println("窈窕走路");} }
import org.w3c.dom.ls.LSOutput;import java.util.Arrays;public class Main {public static void main(String[] args) {Person m1 = new Man();Person w1 = new Women();m1.walk();m1.eat();} } 输出结果为大吃大喝
但是当我调用earnMoney时
import org.w3c.dom.ls.LSOutput;import java.util.Arrays;public class Main {public static void main(String[] args) {Person m1 = new Man();Person w1 = new Women();m1.walk();m1.eat();m1.earnMoney();} }
编译失败了;
2.虚拟方法调用:当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法;
编译时e为person对象,而方法的调用是在运行时确定的,所以调用的是Student类的方法
3.多态使用前提:
(1)类的继承关系
(2)重写方法
4.举例三:不同数据库与java的连接也是通过数据库来实现的:
import org.w3c.dom.ls.LSOutput;import java.sql.Connection; import java.util.Arrays;public class Main {public static void main(String[] args) {}public void doData(Connection conn){conn.method1;conn.method2;conn.method3;} }
通过传入不同java中定义的Connection的子类对象,实现多态,各大数据库厂商通过改写父类中java定义的方法,来实现各自数据库的操作;
5.明确:对象的多态性,只适用于方法,不适用于属性;
属性:编译看左边,运行看左边;
6.多态是运行时行为;
7.重载和重写的区别:
重载是包括父类和子类的,即子类可以重载父类的同名不同参数的方法
重载对于编译器而言,同名方法成了不同的方法,他们的调用地址在编译期就绑定了;
而对于多态,只有等到方法调用那一刻,编译器才会确定所要调用的具体方法,这称为“晚绑定”或者“动态绑定”
8.instanceof操作符:
x instanceof A:检验x是否为A类的或A子类的对象,返回值为boolean型;(是则为true)
9.对象的多态性,内存中实际上加载了子类特有的属性和方法,但是由于声明原因,导致编译时不能调用
如何能调用特有的结构呢?
可以进行向下转换,例如:
import org.w3c.dom.ls.LSOutput;import java.sql.Connection; import java.util.Arrays;public class Main {public static void main(String[] args) {Person m1 = new Man();Person w1 = new Women();Man m2 = (Man)m1;((Man) m1).earnMoney();}} 注意:m1是person类,只能向下强转为自己的子类即Man型,但是不能转为Women型,如果转为women型,则会返回异常:ClassCastException
10.
import org.w3c.dom.ls.LSOutput;import java.sql.Connection; import java.util.Arrays;public class Main {public static void main(String[] args) {Person m1 = new Man();Person w1 = new Women();Order o1 = new Order();System.out.println(o1.getClass().getSuperclass());}}class Order{}
获取到根父类;
11.Object类:
他是根父类,所以它定义了一些通用的方法,但没有定义属性,还声明了一个空参的构造器;
它的一些方法不能直接被子类使用,往往需要进行重写;
(1)equals()方法:
先回顾==运算符:
比较的是基本数据类型变量的数据值以及引用数据类型变量的地址值;
import org.w3c.dom.ls.LSOutput;import java.sql.Connection; import java.util.Arrays;public class Main {public static void main(String[] args) {int i = 10;char c1 = 10;double b1 = 10.0;char c2 = 'A';char c3 = 65;System.out.println(i == b1);System.out.println(i == c1);System.out.println(c2 == c3);}}
结果都为true;
import org.w3c.dom.ls.LSOutput;import java.sql.Connection; import java.util.Arrays;public class Main {public static void main(String[] args) {Customer c1 = new Customer("Tom", 21);Customer c2 = new Customer("Tom", 21);System.out.println(c1.equals(c2));} } class Customer{String name;int age;public Customer(String name, int age){this.name = name;this.age = age;} }
而自己创造的类,调用根父类未重写的equals方法,他的判断相当于==,是判断的地址值;
但是你使用String或者Data对象的equals方法,则是进行对象实体内容的判断,这是因为其内部改写了equals方法;
(2)toString()方法
当我们输出一个对象的引用时,实际上就是调用当前对象的toString()
这是初始的toString方法;
而像String、Date等都重写了Object中的toString方法,此时返回的是实体内容信息;
总结:我们重写这些方法都可以借助idea自动生成;无需自己重写;
12.包装类:Wrapper
(1)针对八种基本数据类型,我们定义了相应的八种包装类,添加了相应的方法:
byte-Byte
shor-Short
int-Integer
float-Float
double-Double
boolean-Boolean
char-Character
13
三种类型之间的转换:
(1)基本数据类型-》包装类:
import org.w3c.dom.ls.LSOutput;import java.sql.Connection; import java.util.Arrays;public class Main {public static void main(String[] args) {int num = 10;Integer int1 = num;System.out.println(int1.toString());int num1 = 20;Integer int2 = Integer.valueOf(num1);System.out.println(int2.toString());} }
两种方法:①自动装箱
②使用静态方法valueOf()
推荐使用自动装箱;
可以使用Integer的方法toString来返回其int值;
import org.w3c.dom.ls.LSOutput;import java.sql.Connection; import java.util.Arrays;public class Main {public static void main(String[] args) {int num1 = 20;Integer int2 = Integer.valueOf("123abc");System.out.println(int2.toString());} }b不能乱传,会触发异常;
(2)包装类-》基本数据类型:
①
调用XXXValue()方法;
import org.w3c.dom.ls.LSOutput;import java.sql.Connection; import java.util.Arrays;public class Main {public static void main(String[] args) {Integer t1 = 12;System.out.println(t1.intValue());} }
②自动拆箱
import org.w3c.dom.ls.LSOutput;import java.sql.Connection; import java.util.Arrays;public class Main {public static void main(String[] args) {Integer t1 = 12;int i2 = t1;System.out.println(i2);} }
(3)基本数据类型、包装类-》String类型:
①连接运算:
import org.w3c.dom.ls.LSOutput;import java.sql.Connection; import java.util.Arrays;public class Main {public static void main(String[] args) {int i1 = 10;String s1 = i1 + ""; } }
②调用String的valueOf方法
import org.w3c.dom.ls.LSOutput;import java.sql.Connection; import java.sql.SQLOutput; import java.util.Arrays;public class Main {public static void main(String[] args) {float f1 = 12.4f;Double d1 = 12.4;String s1 = String.valueOf(f1);String s2 = String.valueOf(d1);System.out.println(s1);System.out.println(s2);} }
(4)String类型-》基本数据类型、包装类
调用包装类的parseXXX(String s);
import org.w3c.dom.ls.LSOutput;import java.sql.Connection; import java.sql.SQLOutput; import java.util.Arrays;public class Main {public static void main(String[] args) {String s1 = "123";String s2 = "true";int i1 = Integer.parseInt(s1);boolean b1 = Boolean.parseBoolean(s2);System.out.println(i1);System.out.println(b1);} }