多态
// 对象能执行什么方法,主要看对象左边的类型,和右边的没有关系
多态:同一方法可以根据发送对象的不同而采用不同的行为方式
父类:
public class Person
{
public void run(){
System.out.println("Person => run");
}
}
子类:
public class Student extends Person{
@Override
public void run() {
System.out.println("Student => run");
}
public void eat(){
System.out.println("Student => eat");
}
}
test.java
public class test {
public static void main(String[] args) {
// 一个对象的实际类型是确定的(左边)
// 指向的引用类型不确定
Person s1 = new Person();
// 父类的引用 指向子类
Person s2 = new Student();
// 对象能执行什么方法,主要看对象左边的类型,和右边的没有关系
s2.run();
s2.eat();
}
}
IDEA可以把s2强制转换为Student
4. 多态存在的条件
存在继承关系
子类重写父类
父类的引用,指向子类:Person person = new Student();
不能多态的情况:
static方法: 属于类的方法
final方法: 最终的,不能被继承重写
private方法: 私有的
5. instance判断是不是类的对象
用于判断对象的运行类型,是否是某个类的类型或者其子类型
// Object>Person>Student
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 String); // 报错了
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
Object object = new Student();
System.out.println(object instanceof String); // false
String string = new String();
System.out.println(string instanceof Object); // !! true
6. 类型转换
父类型引用指向子类型,无法调用子类型的方法,这时将对象强制转换为子类型
((Student) person).eat();
向上转型upcasting:子类对象赋值给父类引用,Father father = new Son();
向下转型downcasting:指向子类对象的父类引用,赋值给子类引用, Son son = (Son)father,这个father就是上面提到的那个father
Tip: 写方法时,父类作为参数,传入子类对象,就是利用了向上转型。这时子类自己的方法不好使,重写了父类的方法的可以用,父类的方法也可以用。
修饰符
static
静态变量属于类,在创建类时分配内存,各对象共享static类变量
非静态变量属于对象,在创建对象时分配内存,对象间不共享
public static void main(String[] args) {
/*
Person <- Student
Person <- Teacher
Person中有static变量name
Student和Teacher中各自有一个变量Age
*/
// s2改变了s1的name,因为name是共享的static变量
Person s1 = new Student();
s1.setName("s1");
System.out.println(s1.name); // s1
Person s2 = new Teacher();
s2.setName("s2");
System.out.println(s1.name); // s2
//s2设置的Age值不会影响到s1,因为是各自的变量,不是类共享的
((Student) s1).setAge(3);
System.out.println(((Student)s1).getAge()); //3
((Teacher) s2).setAge(4);
System.out.println(((Teacher)s2).getAge());// 4
((Student) s1).setAge(3);
System.out.println(((Student)s1).getAge());//3
}
final
修饰类:该类不能被继承
修饰方法:该方法可以被继承,但继承后不能被重写
修饰变量
局部变量:
如果是形参设为final则不能在方法体中赋值,因为已经在传参时赋过一次了。
如果是函数体中的局部变量,只能赋值一次,不能多次赋值
非静态成员变量:声明时赋值; 匿名代码块赋值; 构造器中赋值【可以把声明时赋值和在代码块中赋值理解成一个,都是声明时赋值,写法不一样罢了】
// 声明时赋值
private final int b = 1;
// 匿名代码块赋值
{
final int d = 5;
}
// 构造器赋值
private final int a;
public Person(int a) {
this.a = a;
}
静态成员变量:声明时赋值; 静态代码块赋值
// 静态成员变量:不能在构造器中赋值,声明时赋值
private static final int b = 0;
// 或者用“静态代码块”,也是声明时赋值
static{
int b = 1;
int c = 2;
}
引用变量:正常使用 就是不能再重赋值了
abstract