1.Final
1.是什么
是个修饰符,表示最终的,不可修改的。
2.能做什么
final修饰的类不能被继承
final修饰的成员方法不能被覆写
final修饰的变量不能二次赋值,没有默认值,必须显式赋值
一般我们把final修饰的静态变量叫做 常量 ,也就是public static final 数据类型 变量名 = 值;
注: final、static、public没有先后顺序,都是修饰符
3.怎么用
final修饰的类不能被继承
final class A{
}
class B extends A{ //此时A报错
}
final修饰的成员方法不能被覆写
class A {
public final void m1(){
}
}
class B extends A{
public void m1(){ //此时m1报错
}
}
final修饰的变量,不能二次赋值
final int i = 2;
i = 3;
final修饰的成员变量没有默认值,并且不能二次赋值
final修饰的静态变量没有默认值,不能二次赋值,一般pfs会一起出现,简称常量
public final static int AGE = 18;
4.修饰引用类型
public class Final {
//常量名建议全部大写
public final static int AGE = 18;
final static public void main(String[] args){
int AGE = 0;
final Customer c = new Customer("张三",18);
c.age = 19;
c.name = "李四";
}
}
class Customer{
String name;
int age;
public Customer(String name,int age){
super();
this.name = name;
this.age = age;
}
}
2.多态
1.是什么
父类引用指向子类对象
父类引用:指的是用父类型声明的引用类型变量
指向:通过内存地址可以找到哪个对象
子类对象:new子类 创建的堆内存对象
子类 变量 = new 子类();
Cat c = new 子类();
多态调用方法:父类.类名 = new 子类();
Animal a = new Cat();
注:只继承成员方法
2.相关知识
软件设计六大原则:
1.单一职责原则:功能单一,只拥抱一种变化
2.里氏替换原则:能使用父类的情况下,一定可以使用子类
3.依赖倒置原则:细节应该依赖抽象,而抽象不应该依赖细节
4.接口隔离原则:先不管
5.迪米特法则:最少知识原则,和其他类或对象尽可能有更少的了解
6.开闭原则:对修改关闭,对扩展开放
3.优点
同一操作,作用于不同对象,可以有不同的解释,产生不同的结果,这就是多态性
当一件事会有多种不同实现的方式的时候,我们选择依赖高层,来拥抱多种变化(曹操问文官)
本质还是降低类和细节之间的耦合度
多态的缺点 : 丢失子类特有的属性
多态进行属性调用 :
1 如果父类没有 ,直接报错,不管子类有没有
2 如果父类有,子类没有, 直接执行父类
3 父类和子类都有, 成员方法执行子类,因为成员方法可以覆写,其他的都执行父类
多态又叫向上转型
public class Poly_03 {
public static void main(String[] args) {
// 多态
SupClass sup = new SubClass();
// 父类和子类都有的成员方法 , 执行子类
sup.m1();
// 父类没有,子类有,报错,访问不了
// sup.m2();
// 父类有,子类没有,执行父类
sup.m3();
// 父类和子类都有的 静态方法 执行父类
sup.m4();
// 成员变量,也是执行父类
System.out.println(sup.i);
// 此时 由于多态原因,子类特有属性访问不到,想要访问也行,先进行向下转型
// 必须先发生向上转型,才能发生向下转型
SubClass sub = (SubClass) sup;
sub.m2();
// 没有发生向上转型,如果直接使用向下转型 会报错
SupClass sup1 = new SupClass();
// 类型转换异常
// SubClass sub1 = (SubClass) sup1;
// instanceof : 判断 某个对象是否由某个类实例化而来
if ( sup1 instanceof SubClass) {
// 如果是 在向下转型,不是就不转,可以避免类型转换异常
SubClass sub1 = (SubClass) sup1;
}
}
}
class SupClass {
int i = 1;
public static void m4() {
System.out.println("父类静态方法m4");
}
public void m1() {
System.out.println("父类成员m1");
}
public void m3() {
System.out.println("父类成员m3");
}
}
class SubClass extends SupClass {
public static void m4() {
System.out.println("子类静态方法m4");
}
int i = 2;
public void m1() {
System.out.println("子类成员m1");
}
public void m2() {
}
}
6.多态的几种形式
父类引用指向子类对象
1.直接多态
Sup sup = new Sub();
2.形参和实参,方法参数列表为父类类型,调用方法传入子类对象
m1(new Sub());
3.返回值多态,返回值类型是父类类型,但是返回子类对象
Sup result = m2();
7.Instanceof
判断某个对象是否由某个类实例化而来
if(sup instanceof SubClass){ SupClass sup1 = new SupClass(); //sup1由SupClass实例化而来
SubClass sub1 = (SubClass)sup1;
}
3.abstract
1.是什么
修饰符,修饰的类 是抽象类,修饰的方法是抽象方法
抽象类不能实例化
抽象方法,没有方法体,只定义功能,没有功能的实现,并且抽象方法必须在抽象类中
反之,抽象类中,可以没有抽象方法
abstract不能和final同时出现
2.使用方法
//动物吃饭的功能
abstract class Animal{
public abstract void eat();
public void m1(){
}
}
//实现
class Cat extends Animal{
public void eat(){
}
}
4.Interface
1.是什么
接口,可以理解为完全抽象的一个类,里面只有抽象方法和常量
但是1.8开始,允许出现静态方法和默认方法
语法 修饰符 interface 接口名 {}
接口中的抽象方法不需要加abstract修饰,方法默认都是 public abstract
接口中,没有变量,只有常量,并且 public static final 可以省略
类和接口之间,不再是继承关系,变成了实现关系,由 extends 换成了implements
接口名 变量 = new 子实现类() 也是会发生多态的
一个类 只能继承一个类,但是可以实现N个接口,以 逗号 隔开,可以解决单继承功能变弱问题
class 类名 implements 接口1,接口2……{}
接口和接口之间是多继承,多个 逗号 隔开
interface 接口名 extends 父接口名1,父接口名2……
一个类如果实现了一个接口,那么必须实现接口中所有的抽象方法,否则该类需要加abstract修饰
一个抽象类,实现一个接口,可以实现0~N个抽象方法
1.7 只能有抽象方法
1.8 可以有静态方法,也可以有default方法(就理解为成员方法即可)
静态方法,用接口名调用即可
default 方法需要同过子实现类调用,同时也可以覆写
1.9 开始 支持 private方法
2.使用方法
interface A{
public static final String name ="xx";
// psf可以省略
int age = 2;
public abstract void m1();
// public和abstract可以省略
void m2();
public default void m3(){
System.out.println("默认方法");
}
public static void m4(){
System.out.println("静态方法");
}
}
interface B{
}
// 多继承
interface C extends B,A{
}
// 多实现,需要实现所有的抽象方法
class D implements A,B,C{
@Override
public void m1() {
}
@Override
public void m2() {
}
}
// 抽象类,可以实现0~N个抽象方法
abstract class E implements A,B,C{
}
5.Object
1.概述
所有类的祖类
一个类没有显示继承另一个类的时候,默认继承object
Object xx = new xxx():是可以发生多态的
2.Equals
==:比较基本类型的时候,比较值的大小,比较引用类型的时候,比较的是内存地址
而比较内存地址是没有任何价值的,我们一般会比较两个对象的属性值,是否一致,而不是比较两个对象地址是否一致
equals():该方法设计目的是用来比较两个对象是否相等,但是默认比较地址
java中Object里面的equals方法默认比较内存地址(==)需要我们根据需求进行重写
//需求:如果两个学生ID和姓名相同,则认为这两个是同一个学生
public boolean equals(Object obj){
if(obj instanceof Srudent){
Student s2 = (Student) obj;
if(this.id == s2.id && this.name.equals(s2.name){
ruturn true;
}
}
return false;
}
3.finalize
该方法会在垃圾被回收的时候自动调用,无须程序员手动调用
垃圾:当一个对象没有更多引用指向它的时候,该对象被视为垃圾数据(就是创建了一个对象,谁也找不到它)
protected void finalize() throws Throwable()
Object中的finalize方法什么也没有做,需要自己根据需求进行重写
4.toString
代表了当前对象的字符串表示形式
当我们打印一个引用类型变量的时候会自动调用该方法的toString方法
而Object中默认的toString方法是打印该对象的内存地址(hash值)