抽象类:
java中使用抽象类,限制实例化
java中的对象是对现实世界的具象化,但是在现实世界中,某些类并不具备实例化的意义,因此可以定义为抽象类
抽象类:
1.创建抽象类的时候需要添加 abstract 的关键字
2.不能进行实例化,也就是不能new对象
3.抽象类中的某些方法需要子类进行更丰富的实现,父类实现没有意义,此时可以将抽象类中
的方法定义为抽象方法,没有具体的实现,只包含方法名称,返回值,参数列表,访问修饰符
4.使用abstract关键字修饰的方法叫做抽象方法,可以不写方法的实现
5.子类在继承抽象父类的时候,必须要将父类中的抽象方法进行实现或者将子类也定义为抽象类
6.由抽象方法的一定是抽象类,但是抽象类中不一定包含抽象方法
abstract也可用于方法——抽象方法
抽象方法没有方法体
抽象方法必须在抽象类里
抽象方法必须在子类中被实现,除非子类是抽象类
public abstract class Pet {
private String name;
private int age;
//构造器不能被继承
public Pet(){
}
public Pet(String name,int age){
this.name = name;
this.age = age;
}
//抽象方法
public abstract void print();
public void show(){
System.out.println("Pet show...");
}
}
class Dog extends Pet{
@Override
public void print(){
System.out.println("Dog print...");
}
}
class PetTest{
public static void main(String[] args) {
Dog dog = new Dog();
dog.print();
// Pet pet = new Pet();实例化Pet没有意义
}
}
final的使用:
final可以修饰变量:
表示变量的值不可变
final可以修饰方法:
表示方法不可以被重写
final可以修饰类
表示类不可以被继承
使用final修饰引用型变量,变量的值是固定不变的,变量所指向的对象的属性值是可变的
public /*final*/ class FinalDemo {
public String name;
public static final int num = 10;
// public FinalDemo(){
// super();
// }
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public final void show(){
System.out.println("FinalDemo show...");
}
public static void main(String[] args) {
// FinalDemo fd = new FinalDemo();
// fd.num = 20;
// FinalDemo.num = 20;//静态归属于类
// num = 20;
// System.out.println(num);
//使用final修饰引用型变量,变量的值是固定不变的,而变量所指向的对象的属性值是可变的
final FinalDemo fd = new FinalDemo();
fd.show();
// fd = new FinalDemo();
fd.setName("jason");
System.out.println(fd.getName());
}
}
class FinalSubClass extends FinalDemo{
// @Override
// public void show(){
//
// }
}
object类:
对象的比较==和equals()
:
比较两基本类型变量的值是否相等
比较两个引用类型的值即内存地址是否相等,即是否指向同一对象。
equals() :
两对象的内容是否一致
示例
object1.equals(object2) 如:p1.equals(p2)
比较所指对象的内容是否一样
是比较两个对象,而非两个基本数据类型的变量
(:如果是基本对象比值,如果是引用数据比引用地址)
object1 == object2 如:p1==p2
比较p1和p2的值即内存地址是否相等,即是否是指向同一对象。
自定义类须重写equals(),否则其对象比较结果总是false。
Object类是所有Java类的根基类
如果在类的声明中未使用extends关键字指明其基类,则默认基类为Object类
重写:toString方法:
默认返回:包名+类名+@+哈希码
可以重写!
继承深化
父类方法的重写:
“==”:方法名、形参列表相同。
“≤≤”:返回值类型和异常类型,子类小于等于父类。
“≥”:访问权限,子类大于等于父类
构造方法调用顺序:
根据super的说明,构造方法第一句 总是:super(…)来调用父类对应的构造方法。
先向上追溯到Object,然后再依次向下执行类的初始化块和构造方法,直到当前子类为止。
public class Teacher {
private String name;
private int age;
private double salary;
public Teacher(){ }
public Teacher(String name,int age,double salary){
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
public double getSalary(){
return salary;
}
public void setSalary(double salary){
this.salary = salary;
}
// @Override
// public boolean equals(Object o){
// Teacher t = (Teacher) o;
// return (this.name == t.name && this.age == t.age && this.salary == t.salary)
// }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Teacher teacher = (Teacher) o;
return age == teacher.age &&
Double.compare(teacher.salary, salary) == 0 &&
Objects.equals(name, teacher.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age, salary);
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
'}';
}
// @Override
// public String toString(){
// return ("name:" + this.name + "age:" + this.age + "salary:" + this.salary);
// }
public static void main(String[] args) {
Teacher t1 = new Teacher("张飞",28,9000);
// Teacher t2 = t1;
Teacher t2 = new Teacher("张飞",28,9000);
// System.out.println(t1 == t2);//true false
// t2.setName("赵云");
System.out.println(t1.equals(t2));//true false
System.out.println(t1);
}
}
引用类型的转换跟基本数据类型的转换类似:
1.当父类需要转成子类的时候,要进行强制转换,但是在强制转换之前一定要先判断父 类引用指向的子类对象到底 是谁,如果无法确定,在运行过程中可能出错
2.当子类需要向父类转换的时候,直接自动转换,不需要进行任何的判断 引用数据类型 的类型转换
子类转换为父类:自动转换
上转型对象不能操作子类新增的成员变量和方法。
上转型对象可以操作子类继承或重写的成员变量和方法
如果子类重写了父类的某个方法,上转型对象调用该方法时,是调用的重写方法。
父类转换为子类:强制转换
(绝不是做手术,而是父类的真面目就是一个子类,否则会出现类型转换错误)
多态:
对应同一个指令(调用同一个名称的方法),不同的对象给予不同的反应(不同的方法实现)
规范(多态实现的前提):
1.必须要有继承关系
2.子类方法必须重写父类的方法
3.父类引用指向子类对象(子类实例)
多态的目的:
1.为了提高代码的扩展性和维护性
2.方便代码逻辑的编写
多态的两种表现形式:
1.父类作为方法的参数
2.父类作为方法的返回值类型
什么是多态
生活中的多态
不同类型的打印机打印效果不同
同一种事物,由于条件不同,产生的结果也不同 父类引用,子类对象
程序中的多态
多态:同一个引用类型,使用不同的实例而执行不同操作
如何实现多态
使用多态实现思路
编写父类
编写子类,子类重写父类方法
运行时,使用父类的类型,
类型转换
向上转型——子类转换为父类,自动进行类型转换
向下转型——父类转换为子类,结合instanceof运算符进行强制类型转换
多态 polymorphism
多态性是OOP中的一个重要特性,主要是用来实现动态联编的,换句话说,就是程序的最终状态
只有在执行过程中才被决定而非在编译期间就决定了。这对于大型系统来说能提高系统的灵活性和扩展性。
java中如何实现多态?使用多态的好处?
实现多态的两种方式
使用父类作为方法形参实现多态
使用父类作为方法返回值实现多态
使用多态的好处?
多态可以减少类中代码量,可以提高代码的可扩展性和可维护性
引用变量的两种类型:
编译时类型(模糊一点,一般是一个父类)
由声明时的类型决定。
运行时类型(运行时,具体是哪个子类就是哪个子类)
由实际对应的对象类型决定。
多态的存在要有3个必要条件:
要有继承,要有方法重写,父类引用指向子类对象
instanceof运算符
对象 instanceof 类或接口
instanceof通常和强制类型转换结合使用