多态
◆ 动态编译:类型:可扩展性
◆ 即同一方法可以根据发送对象的不同而采用多种不同的行为方式。
◆ 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类、有关系的类)
◆ 多态存在的条件
-
有继承关系
-
子类重写父类方法
-
父类引用指向子类对象
◆ 注意:多态是方法的多态,属性没有多态性。
◆ instanceof (类型转换)引用类型,判断一个对象是什么类型
- 基础类型转换的高低关系:是指容量的大小
- 引用类型转换:是指父类和子类
- instanceof可以判断两个类之间是否存在父子关系,有父子关系就OK
多态存在条件
package com.oop;
import com.oop.demo05.A;
import com.oop.demo05.B;
import com.oop.demo06.Person;
import com.oop.demo06.Student;
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Student();
//new Person();
//可以指向的引用类型就不确定了:父类的引用指向子类
//Student 能调用的方法都是自己的或者继承父类的!
Student s1 = new Student();
//Person 父类型,可以指向子类,但是不能调用子类独有的方法
Person s2 = new Student();
Object s3 = new Student();
s2.run();//子类重写了父类的方法,执行子类的方法
s1.run();
/*
结果:son
son
*/
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大!
((Student) s2).eat();//s2.eat()强制转换
s1.eat();
/*
Java里的方法调用,它是运行时和动态对象绑定的
就像eat,他运行之前他并不知道执行了什么,他也不知道会被哪个方法调用
因为我们之间可以存在类型之间的转换
*/
}
}
package com.oop.demo06;
public class Student extends Person{
@Override
public void run() {
System.out.println("son");
}
public void eat(){
System.out.println("eat");
}
}
package com.oop.demo06;
public class Person {
public void run(){
System.out.println("run");
}
}
/*
多态注意事项:
1. 多态是方法的多态,属性没有多态
2. 父类和子类,有联系 否则会类型转换异常!(例如String 与 Object 就不可以) ClassCartException!
3. 存在条件:继承关系,方法需要重写,父类引用指向子类对象! Father f1 = new Son();
不能重写的方法:
1. static 方法,属于类,它不属于实例;
2. final 常量(无法改变的,它是在常量池里的)
3. private 方法
*/
instanceof
package com.oop;
import com.oop.demo06.Person;
import com.oop.demo06.Student;
import com.oop.demo06.Teacher;
public class Application {
public static void main(String[] args) {
//Object > String
//Object > Person > Teacher
//Object > Person > Student
Object object = new Student();
//System.out.println(X instanceof Y);//能不能编译通过,就取决于X和Y之间是否存在父子关系;
//结果是true或者false ,X所指向的实例类型是Y的子类型,或者 X和 Y是有关系的
System.out.println(object instanceof Student);//true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof Teacher);//false,Teacher是另一条线,跟Student无关,跟这个类型一点关系都没有
System.out.println(object instanceof String);//false,String是 Object lang包下面的,更没关系了
System.out.println("===================================");
Person person = new Student();
System.out.println(person instanceof Student);//true
System.out.println(person instanceof Person);//true
System.out.println(person instanceof Object);//true
System.out.println(person instanceof Teacher);//false
//System.out.println(person instanceof String);//编译报错!string和 person同级,它是两条线
System.out.println("===================================");
Student student = new Student();
System.out.println(student instanceof Student);//true
System.out.println(student instanceof Person);//true
System.out.println(student instanceof Object);//true
//System.out.println(student instanceof Teacher);//false,编译报错!
// instanceof是一个比较转换的过程,比较肯定是两边有关系的才会返回true或者false
//System.out.println(student instanceof String);//false,编译报错! 两者没关系会直接报错
}
/*
结果:
true
true
true
false
false
===================================
true
true
true
false
===================================
true
true
true
*/
}
package com.oop.demo06;
public class Student extends Person{
public void go(){
}
}
package com.oop.demo06;
public class Teacher extends Person{
}
package com.oop.demo06;
public class Person {
public void run(){
System.out.println("run");
}
}
类型转换
package com.oop;
import com.oop.demo06.Person;
import com.oop.demo06.Student;
import com.oop.demo06.Teacher;
public class Application {
public static void main(String[] args) {
//类型之间的转化: 基本类型转换,满足高-->低需要强转(可能会丢失精度),低-->高则不需要强转 64/32/16/8位
//类型之间的转化:父 子
//高 低
Person obj = new Student();
//student将这个对象转换为Student类型,我们就可以使用Student类型的方法了!
//高 --> 低 :需要强制转换
Student obj1 = (Student) obj;
//子类转换为父类,可能丢失自己的本来的一些方法!
Student student = new Student();
student.go();
Person person = student;
}
/*
多态总结:
1. 父类引用指向子类的对象(子类引用指向父类的对象肯定是不行的)
2. 把子类转换为父类,也就是向上转型:不用强制转换;
3. 把子类转换为父类,也就是向下转型:需要强制转换;(可能会丢失一些方法)
4. 方便方法的调用,减少重复的代码!简洁
抽象:封装、继承、多态! 抽象类,接口
*/
}
package com.oop.demo06;
public class Student extends Person{
public void go(){
System.out.println("go");
}
}
package com.oop.demo06;
public class Teacher extends Person{
}
package com.oop.demo06;
public class Person {
public void run(){
System.out.println("run");
}
}
static 关键字
静态属性
package com.oop.demo07;
//static
public class Student {
private static int age;//静态的变量 多线程!
private double score;//非静态的变量
public static void main(String[] args) {
Student s1 = new Student();
System.out.println(Student.age);//类变量跟类中的所有实例共享
//System.out.println(Student.score);这是不行的
System.out.println(s1.age);
System.out.println(s1.score);
}
}
静态方法
package com.oop.demo07;
//static
public class Student {
private static int age;//静态的变量 多线程!
private double score;//非静态的变量
public void run(){//非静态方法可以调用静态方法里的所有东西
go();
}
public static void go(){//静态方法可以调用静态方法里的所有东西
}
public static void main(String[] args) {
new Student().run();//对象.方法
Student.go();
go();
}
}
静态代码块
package com.oop.demo07;
public class Person {
//2:赋初值~
{
//代码块(匿名代码块)
//没有名字,程序不会主动调用这些模块
//匿名代码块:创建对象时就自动创建了,而且在构造器之前
System.out.println("匿名代码块");
}
//1 : 只执行一次~
static {
//静态代码块
//可以在里面加载一些初始化的数据
//静态代码块:类一加载就直接执行,永久只执行一次
System.out.println("静态代码块");
}
//3
public Person(){
System.out.println("构造方法");
}
public static void main(String[] args) {
Person person1 = new Person();
System.out.println("=================");
Person person2 = new Person();
}
/*
结果:
静态代码块
匿名代码块
构造方法
=================
匿名代码块
构造方法
*/
}
package的一些新特性
package com.oop.demo07;
//静态导入包~
import static java.lang.Math.random;
import static java.lang.Math.PI;
public class Test {
public static void main(String[] args) {
System.out.println(random());
System.out.println(PI);
}
/*
final 通过final修饰的类不能被继承,就没有子类
*/
}