面向对象整个知识点,以及细节
类与对象
方法调用
1.同一个类中方法调用:直接调用
2.跨类中调用方法:先创建类的对象,再调用方法
3.访问修饰符
传参
基本数据类型---->值
引用类型----->地址
方法重载
方法名:必须相同
形参列表:必须不同(可以是数量,类型。位置不同)
返回类型:无要求
可变参数
访问修饰符 返回类型 方法名 (数据类型...方法名)
public int sum (int ..nums)
1)可变参数的实数:0/多个
2)可变参数的实数:可以使数组
3)可变参数的本质:数组
4)可以和普通类型参数一起用(但是,可变参数在最后,并且只能一个)
作用域
1.主要的变量:属性(成员变量) 局部变量
2.局部变量---作用域:成员方法中定义的变量
3.全局变量/属性---作用域:整个类
4.全局变量:有默认值,可以不赋值
5.局部变量:没有默认值,必须赋值
6.局部变量:没有修饰符
细节:
1.属性和局部变量可以重名,就近原则
2.属性:生命周期长,伴随着对象的创建而创建,销毁而销毁
局部变量:生命周期短,伴随着 方法/代码块 的执行而创建,销毁而销毁。(栈)
3.属性:可以被本类/其他类使用(通过对象调用)
局部变量:只能在本类中对应的方法中使用 (所以,不用修饰符)
4.属性/全局变量:有访问修饰符
局部变量:没有修饰符
构造器
1.修饰符;public protected 默认 private
2.无返回值
3.方法名和类名一样
4.参数列表和成员方法一样(一对一)
5.构造器调用,由系统自动调用该类的构造器,完成对象的初始化
6.构造器目的:完成对象的初始化,而不是创建对象
细节:
1.一个类可以定义多个不同的构造器(构造器的重载)
2.没有定义构造器,系统自动的分配一个默认的无参构造器
可以通过javap反编译查看这个无参构造器
3.一旦定义有参构造器--->默认的无参构造器会被覆盖
除非显示的定义:Dog(){}
this
Java虚拟机会给每个对象分配一个this,代表当前对象
哪个对象调用----> this就代表那个对象
1.this 可以访问本类:属性,方法,构造器
2.this 用于区分当前类的属性和局部变量
3.this.方法名(参数列表)
4.this(参数列表) 只能在构造器中使用,第一行!
A构造器中访问B构造器
5.this 只能在类定义的方法中使用!!不能在类定义的外部用
包
作用:1.区分相同的类 2.控制访问范围
细节:1.package 作用:声明当前类所在的包
位置:最上面,一个类对应一个包
2.import 指令:放在 package 下面,类定义上面
访问修饰符
细节:
1.类:只能默认 ,public
2.成员方法的访问规则和属性一样
public:公开方法,所有包,类都可以访问
protected :同包+不同包的子类
默认:同包
private :同类
封装
好处
1.隐藏实现的细节
2.对数据进行验证,保证安全合理
步骤
1.属性私有化
2.public void setXXX(类型 形参列表){
验证输入的准确性
安全性
}
3.public 数据类型 getXXX(){
安全性
return XXX;
}
继承
目的:解决类的复用性
class 子类 extends 父类 {}
1.子类会自动拥有父类定义的属性和方法
2.父类:超类,基类
3.子类:派生类
细节
1.子类继承了父类所有属性和方法
(非私有--->直接访问 私有--->父类公共方法)
2.子类必须调用父类的构造器,完成父类初始化 super
3.子类默认调用父类无参构造器(父类没有无参构造器,必须指定)
4.super 第一行!只能在构造器中用
5.this 第一行!所以,super 和 this 不共存!!
6.用this--->父类没有 有参构造器
7.所有类都是Object 类的子类,Object是所有类的基类
8.父类super--->追溯到Object类
9.子类最多继承一个父类(直接继承)
10. 父类子类满足: is-a 关系! (因为父类是从子类的冗余部分提出来的)
继承本质
1.首先看子类是否有该属性
2.子类有,并且可以访问---->返回信息
3.子类没有,看父类有没有?能不能判断?
有,但是不能访问--->cannot access 编译报错
有,能访问--->
没有,继续看父类,继续找
继承内存布局
内存加载顺序:
堆:先加载顶级类-->子类-->子类
方法区:顶级类-->子类-->子类
细节:继承设计基本思想(分工明确)
父类构造器--->完成父类的初始化
子类的构造器--->完成子类的初始化
super
1.访问父类的属性,但不能访问父类的 private 属性。
super.属性名;
2.访问父类的方法,但不能访问父类的 private 方法
super.方法名(参数列表);
3.访问父类的构造器
super(参数列表); 第一行!!只能一次!
细节
super 的访问不限于直接父类!爷爷类也可以
没有:跳到父类找
有,但是不能访问--->报错!cannot access
多个父类都有同名的成员:就近原则
想访问父类:uper.xx
不重名:super this 直接访问 一样!!
找不到--->提示方法不存在
super VS this
this super
访问属性 从本类开始找 从父类开始找
调用方法 从本类开始找 从父类开始找
调用构造器 调用本类构造器 调用父类构造器
特殊 当前对象 子类中访问父类对象
方法重写
细节
1.子类方法:形参列表,方法名称和父类一样!
2.子类的返回类型 ≤ 父类的返回类型
3. 子类的访问权限 ≤ 父类的访问权限
public,protected,默认,private private
public,protected,默认 默认
public,protected protected
public public
方法的重写 VS 重载
形参列表 返回类型 修饰符(访问权限)
重载 不一样 无要求 无要求
重写 一样 子类≤父类 子类≤父类
多态
方法的多态:重写和重载
对象的多态:
1.编译类型:定义对象时确定,不能改变
2.运行类型:可变化的
3.编译类型XX=new 运行类型()
多态的向上转型
本质:父类的引用--->子类的对象
语法:父类类型 引用名=new 子类类型();
特点:有父类的编译类型(属性+接口)
动态绑定机制:先判断此方法在父类中有没有定义
有定义:从运行类型开始找方法。如果运行类型没有此方法,那就从父类开始找方法。
找到具体方法后,从运行类型开始执行具体方法。
没有定义:直接报错!!因为,编译类型没有此方法执行,肯定报错!
方法找到后,属性:在那个类,就看那个类,没有多态绑定机制。
总结:向上转型的引用:不能访问编译类型 private 成员,无法访问运行类型的特有方法
多态的向下转型
细节:先向上转型--再-->向下转型
语法:子类类型 引用名 =(子类类型) 父类引用;
特点:只能强制转父类的引用,不能强制转父类的对象
要求父类的引用必须指向当前目标类型的对象
目的:向下转型后,才可以调用子类的特有成员
多态参数:向上转型
equals 方法
== :基本数据类型--->值 引用类型--->地址
equals :引用类型:重写过的-->按照特定类型判断值(比如String,int)
没有重写过:地址
equals :不能判断基本数据类型
hashcode
优点:
1.提高具有哈希结构的容器的效率
2.两个引用--->同一个对象:hashcode 一样!
不同对象:hashcode不一样!(有可能一样)
3.hashcode---通过计算--->地址
4.hashcode 根据指向的对象,会变!!
5.真正的地址:不会变!!!
6.C,C++语言,可以直接访问地址。
7.由于Java在JVM上运行,所以无法访问地址。
toString 方法
默认返回:全类名+@+哈希值的16进制
经常会被重写
finalize
1.当对象被回收时,系统自动调用对象的finalize方法
子类可以重写finalzie方法,做一些释放资源的操作
2.什么时候回收?
当某个对象没有被引用时,JVM认为这个对象是垃圾对象,就会使用垃圾回收机制来销毁对象。
销毁前调用finalize方法
3.垃圾回收机制的调用,由系统来决定(GC算法)
也可以通过System.gc()主动触发垃圾回收机制,但有时候不能触发。
4.有时候,整个程序结束了,可能还没垃圾回收。这时候,finalize方法看不出来,但是,早晚会被回收。
类变量
核心:1.static 变量是同一个类所有对象共享
2.static 类变量,在类加载时就加载
类变量,也叫静态变量,是该类的所有对象共享的变量
任何一个该类的对象去访问它时,取到的都是相同的值
同样,任何一个该类的对象去修改它时,修改的也是同一个变量。
定义:访问修饰符 static 数据类型 名;
static 访问修饰符 数据类型 名;
访问:类名.变量名 对象名.变量名
A.name = a1.name = a2.name
细节
1.什么时候需要类变量?
让某个类的所有对象共享一个变量时,使用类变量
2.静态变量 VS 非静态变量 区别
静态变量:类加载时加载,该类所有对象共享
非静态变量:new时加载,每个对象独享
3.加上 static :类变量(静态变量)
不加:实例/普通/非静态变量
4.实例变量不能通过:类名.变量名 访问
5.类变量生命周期:随类加载开始,随类销毁而销毁
类方法
定义:访问修饰符 static 返回类型 方法名 (){}
static 访问修饰符 返回类型 方法名 (){}
当方法中不涉及任何和对象相关的成员---->此方法:静态方法
Math类。Arrays类 直接用,不用创建对象
细节
1.类方法和普通方法---->随类的加载而加载,结构信息存在方法区
2.类方法:无 this,super
3.普通方法和对象有关,先 new,后加载
4.类方法(静态方法)--->只能访问静态变量,静态方法
5.普通方法:什么都可以访问
public static void main (String[]args)
public:mian方法在虚拟机JVM上运行,不在这个类中
static:用main方法,为了不创建对象直接用
如果不用static,用一次,new一次main,那样会存在多个main,多个入口,肯定不行
void:没有返回值
String[]args:cmd上运行a b c--->输出 a b c
代码块
代码化块(又称:初始化块),类的一部分
特点:没有方法名,没有返回值,没有参数列表,只有方法体
细节
1.默认 / static
2.static{}:静态代码块 {}:普通/非静态代码块
3.{} or {}; 都行
本质:{}是构造器的父类!!构造器的冗余部分,放在{}里面
细节
1.static{}:随着类的加载而加载,只执行一次!
{}:new 一次,执行一次!隐式调用
2.类什么时候加载?
①创建对象实例 new
②创建子类对象实例,父类也会被先加载
③使用类的静态成员(静态方法/静态属性)
A --> B --> C
构造器--super-->顶级类==> 静:属性,{} 3 2 1
非静:属性,{} 8 6 4
构造器: 9 7 5
设计模式
单例模式
1.采取一定的方法保证整个软件系统中,对某个类只能存在一个对象实例,并且,该类只提供一个取得对象实例的方法
步骤
①构造器私有化---->防止new
②类的内部创建:一开始创建---->饿汉式 ==null时创建---->懒汉式
③想外暴露一个静态的公共方法 getInstance
饿汉式 VS 懒汉式
1.区别:创建对象的时机不同
饿汉式:类加载就创建对象 懒汉式:使用时才创建
2.饿汉式:不存在线程问题 但,存在浪费空间资源
3.懒汉式:存在线程问题 但,不浪费空间资源
final
可以修饰:类,属性,局部变量
1.不希望类被加载:final class A{}
2.不希望弗雷中某个方法被子类重写: public final void hi(){}
3.不希望类的属性被修改:public final int TAX_RAT=5;
4.不希望类的局部变量被修改:final int TAX_RAT=5;
细节
1. final 属性---->常量 XXX_XXX_XXX
2. final 属性定义时,必须赋初值,并以后不能修改
赋值:①定义时:public final int TAX=4;
②构造器中
③代码块中
3. final--->static 属性:①定义时 ②静态代码块中
4. final class A{} 不能被继承,但是,可以实例化对象
5.非 final 类,但有 final 方法--->同样可以继承
6. final 类---->对象默认 final 方法! 不能继承类,就无法重写方法(有 final 一样)
7. final--->不能修饰构造器
8. static final + int i=6; 用6,不会导致类加载,底层编译做了优化
9.包装类(Integer,Double,Float,Boolean),String---->final 类
抽象类
父类方法的不确定性(比如:动物类)
当父类的某些方法,不能确定时,可以将其声明为“抽象方法”,那么这个类:抽象类
1.访问修饰符 abstract 类名 {}
2.访问修饰符 abstract 返回类型 方法名(参数列表); 没有方法体
3.抽象类的价值:设计,让子类继承并实现抽象类
细节
1.抽象类不能被实例化
2.抽象类可有可无 abstract 方法
3.一旦类包含了 abstract 方法---->这个类必须是:abstract 类
4. abstract 只能修饰:类 ,方法
5.抽象类可以有任意成员(包括构造器)
6.抽象方法不能有主体,不能实现。只能靠继承来实现
7.一个类继承了抽象类---->子类必须实现抽象类的所有抽象方法
除非:这个类也是抽象类
8.抽象方法不能使用 private,final,static 。因为这些和重写违背!
抽象方法--->必须被重写
模板
当功能内部一部分实现是确定的,一部分实现不确定。
这时可以吧不确定的部分暴露出去,让子类实现。
接口
interface 接口名 { class 类名 implements 接口 {
属性 自己属性;
抽象方法 自己方法;
} 必须实现接口的抽象方法; }
小结:接口是更加抽象的抽象的类,抽象类里的方法可以有方法体。
接口里的所有方法都没有方法体
JDK8以后,接口里面可以有:静态方法,默认方法(可以有具体实现)
细节
1.接口不能被实例化
2.接口中所有方法是 public 方法,接口中抽象方法:void aa(); == abstract void aa();
3.一个普通类实现接口,就必须将该接口的所有方法都实现
4.抽象类实现接口,可以不用实现接口的方法
5.一个类同时可以实现多个接口
6.接口的属性:final 而且,public static final
int a=4; ---> public static final int a=4;
7.接口中属性的访问形式:接口.属性名
8.接口不能继承其它的类,但可以继承多个别的接口
9.接口:public 和 默认
接口的多态
1.多态参数---->向上转型
2.多态数组
3.接口存在多态传递现象
接口 VS 继承
继承:解决代码的复用性,可维护性
接口:规范,让其它类去实现这些方法
接口比继承更加灵活
继承:is-a 接口:like-a
抽象类:表示属于什么 猫属于动物,大卡车属于车
接口:表示干什么 猫会跑,狗会跑也会游泳
内部类
一个类的内部(外部类)又完整的嵌套了另一个类(内部类)的结构。
类五大成员:属性,方法,构造器,代码块,内部类
内部类最大特点:直接访问外部类的私有属性,并且可以提现类与类之间的包含关系
class Outer { //外部类
public void f() {
class Inner {} //局部内部类
}
}
class Other{ //外部其它类
}
局部内部类
1.可以直接访问外部类的所有成员(包括 private )
2.不能添加访问修饰符(局部变量),可以 final 修饰
3.作用域:仅限在方法中
4.局部内部类---访-->外部类:直接访问
5.外部类---访-->局部内部类:先创建对象,在访问(在作用域内)
6.定义范围:方法/代码块中
作用域:方法/代码块中
7.外部其它类---不能访-->局部内部类
8.外部类和局部内部类重名:就近原则
调用外部类:外部类名.this.成员 Outher.this.n1
直接访问: n1
匿名内部类
1.该类没有类名,类名由系统分配。
同时还是一个对象
2.定义在外部类的局部位置
new 类/接口(参数列表){
类体
}; 系统分配的类名:Outher$1
IA tiger = new IA(){ class Outher$1 implements IA {
public void cry(){}; 内部: public void cry(){ }
} }
3.匿名内部类“既是一个类的定义,同时它本身也是一个对象
既有定义类的特征,也有创建对象的特征
4.可以直接访问外部类的所有成员(包括 private )
5.不能加访问修饰符(本身局部变量)
6.作用域:方法体/代码块中
7.匿名内部类---访-->外部类:直接访问
8.外部其他--不能访-->匿名内部类
9.外部类和局部内部类重名:就近原则
调用外部类:外部类名.this.成员 Outher.this.n1
直接访问: n1
class Outer { //外部类
class Inner{} //成员内部类
}
class Other{ //外部其它类
}
成员内部类
定义:定义在外部类的成员位置,没有 static 修饰
1.可以直接访问外部类的所有成员(包括 private )
2.可以加任意修饰符
3.作用域:和普通成员一样
外部类的成员方法中调用:先创建成员内部类对象,再调用方法
4.成员内部类---访-->外部类:直接访问
5.外部类---访-->成员内部类:创建对象,再访问
6.外部其它类---访-->成员内部类
7.外部类和局部内部类重名:就近原则
调用外部类:外部类名.this.成员 Outher.this.n1
直接访问: n1
class Outer { //外部类
static class Inner{} //成员内部类
}
class Other{ //外部其它类
}
成员内部类
定义:定义在外部类的成员位置,有 static 修饰
1.可以直接访问外部类的所有成员(包括 private )
2.可以加任意修饰符
3.作用域:和普通成员一样
外部类的成员方法中调用:先创建成员内部类对象,再调用方法
4.静态内部类---访-->外部类:直接访问
5.外部类---访-->静态内部类:创建对象,再访问
6.外部其它类---访-->静态内部类
7.外部类和局部内部类重名:就近原则
调用外部类:外部类名.this.成员 Outher.this.n1
直接访问: n1
Java面向对象整个知识点,以及所有细节
于 2023-11-29 00:59:03 首次发布