20220722学习内容 面向对象概述 五

一  关键字final:

 意思是最终的、不可变的
修饰变量
Final 修饰变量时,变量被必须初始化,并且不能被修改。初始化可以定义 final 变量时直接初始化或者在 构造函数中初始化
修饰局部变量
修饰方法
final 修饰方法则该方法不能被子类重写
修饰类
final 修饰一个类 , 则该类不能被继承
扩展
表示字串的 3 种类型 String StringBuffer StringBuilder 都是 final 类型的类,所以都不允许继承
总结
final 属性上可以声明的同时直接赋值或者在构造器中赋值
final 临时变量,可以声明的同时赋值或者在第一次使用之前进行赋值
注意: final 类型的变量一旦赋值则不允许修改,但是如果是复杂类型是不允许修改地址,但
是可以修改属性
final 方法表示这个方法不允许在子类中重新定义(覆盖 \ 重写)
final 类表示这个类不允许被继承
实现类不能被继承的方法
private 私有构造器
单例模式
        模式:由专家总结出来的在某种情况下解决某类问题的最佳解决方案,是思想、是知识,是一种抽象的 内容
        意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
        主要解决:一个全局使用的类频繁地创建与销毁。
        何时使用:当您想控制实例数目,节省系统资源的时候。
单例模式有多种写法,最常见的是懒汉模式和饿汉模式
(1)饿汉单例模式
优点:没有加锁,执行效率会提高
缺点:类加载时就初始化,浪费内存
编程实现: 私有构造器
静态的私有属性
公共的静态方法
(2)懒汉单例模式
懒汉式:主要是针对饿汉式中不管是否需要使用对象都先创建对象所引起的内存浪费
优点:由于采用延迟处理的方式,所以比较节约内存
缺点:在多线程不能正常工作

二  静态static关键字:

        用于修饰成员
        随着类加载,随着类消失
        优先于对象,用类名直接访问
(1.)静态属性
        static属性是当前类的所有对象所共有的共同属性 ( 只有一个,而普通属性各个对象都有自己的,相互隔 离) ,任何一个当前类对象修改这个属性,所有其他类对象的这个属性都会受影响
典型应用:统计 A1 类的构建次数
(2.)执行顺序
静态属性 --- 属性 --- 构造器
(3.)访问的方式
可以使用 类名 . 静态属性名 或者 对象名 . 静态属性名 的方式进行访问。【范围限制】
(4.)定义常量
命名规则:名称全大写,下划线分词
声明语法: public static final double MIN_NUMBER = 0.1;
声明的同时直接进行初始化
先声明后在 static 静态块中赋值
(5.)静态方法
因为可以直接使用 类名 . 方法名 的形式直接调用静态方法,静态方法执行时很有可能并没有构建对
象,所以在静态方法中不允许使用 this/super 之类用于指定对象的关键字
当然在静态方法中允许创建对象,并调用对象方法
静态方法只能直接访问静态成员,不能直接访问非静态成员
static 关键字表明一个成员变量或者是成员方法可以在没有所属的类的实例变量的情况下被访问。
Java static 方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而 static 方法是编译时静态绑定 的。static 方法跟类的任何实例都不相关,所以概念上不适用。
(6.) 静态块
类在执行时需要通过一个叫作类加载器的组件将程序加载到内存中,类在运行时一般不会发生变
化,所以类不会频繁加载,在整个运行过程中只加载一次,而且常驻内存
静态块在类加载完毕后自动执行,而且只执行一次
(7.)非静态块
非静态块在类内且在所有的方法之外,非静态块并不会在类加载后自动执行,而是在构建当前对象时自
动执行。 new 一次则会执行一次,执行时机在构造器之前执行
考试点
当类加载完毕会自动优先处理static属性和static块,这两个优先级是相同的,所以谁在前先处理谁
new对象时,处理非静态属性和非静态块,这两个优先级是相同的,所以谁在前先处理谁
最后执行构造器
使用注意事项
静态方法只能访问静态成员,静态有访问局限性
静态方法中不能有this super关键字
主函数是静态的
(8.)什么时候使用静态
当成员变量的数据各个对象都相同时,可以用 static 修饰的,让多个对象共享
方法如果访问了特有数据(非静态成员变量),该函数是非静态的。方法如果没有访问特有数据,
那么该方法就是静态修饰
如果类中的功能都是静态的,那么该类创建对象是没有意义的,所以构造方法需要私有化
(9.)静态导入
在一个类中反复使用到某个类中的静态方法,如果使用静态导入则在当前类中不需要再写类名称
JDK5 当中提供了导入静态方法的 import 语句。
语法: import static java.lang.Math.*; - 导入 Math 类中的所有静态方法
注意要求使用 JDK1.5+ 版本,否则编译不通过

三   成员应用细节:

double a1=-12.345;
System.out.println(Math.abs(a1));
System.out.println(Math.cos(a1));
System.out.println(Math.sin(a1));
import static java . lang . Math . * ;
public class Test1 {
public static void main ( String [] args ) {
double a1 = - 12.345 ;
System . out . println ( abs ( a1 ));
System . out . println ( cos ( a1 ));
System . out . println ( sin ( a1 ));
}
}
(1.)变量分类:
        局部变量:方法体中声明
        成员变量:方法体外类内声明
        实例变量:没有static修饰符,各个不同对象相互隔离
        静态变量::有static修饰符,这个类的所有对象共享
(2.)栈和堆的区别
        管理方式:栈自动释放,堆需要GC
        空间大小:栈比堆小
        碎片相关:栈产生的碎片远小于堆
        分配方式:栈支持静态和动态分配,而堆仅仅支持动态分配
        效率:栈的效率比堆高
(3.)方法的问题
        1.)方法的分类:
无参无返(没有参数列表,没有返回值)单纯的作为 功能代码的聚合使用 便于功能复用
无参有返(没有参数列表,有返回值)
有参无返(有参数列表 没有返回值)适用于功能需要根据参数来进行计算的情况,但是计算的最终 结果又无需返回处理
有参有返(有参数列表,有返回值)适用于功能需要根据参数来进行计算的情况,而且最终的结果
需要返回处理
        2.)方法的形参和实参:
形参 :是定义在方法声明上,用于指定该方法需要传递的参数类型的
实参 :是调用方法时,实际传递的参数值
(4.)方法参数传递
基本数据类型作为参数传值:传值传的时值的内容,来到另一个方法空间之后,这个值和之前没有
任何关系。(如你们拷贝我分享的网盘内容不会改变我原有玩盘内容)
引用数据类型作为参数传值:传值传的时对象在堆的地址值,所以了两个内容指向了同一空间是相
互影响的。(如你登陆我的网盘拷贝内容改变的话会改变我的网盘内容)
(5.)基本数据类型的对象缓存
在不可变类 Integer 类定义中查看源代码可以发现一个定义
是因为在 Integer 中包含有一个缓存池,缓存值为 -128 127 之间。
定义 Integer k1=12 是先在缓存池中查找 12 这个对象,如果有则直接使用
new Integer(12) 一定会引发对象的创建,而不管缓存池中是否包含这个对象
private static class IntegerCache {} 这实际上就是 Integer cache
Integer num1 = 12 ;
Integer num2 = 12 ; 这块相等, <= 127 都是真的
System . out . println ( num1 == num2 );
Integer k1 = 12 ;
Integer k2 = 12 ;
System . out . println ( k1 == k2 ); //true,k1 k2 都是引用类型,所以 == 比较的是地址
Integer k3 = new Integer ( 12 );
System . out . println ( k1 == k3 ); //false
Integer\Long\Short\Byte中都有缓存池、 character 中也有缓存池, boolean 只有 true/false 两个

三  字符串缓存池:

String 中包含一个缓存池,当使用某个字符串对象时会首先在缓存池中进行查找,如果存在则直接返回
这个对象的地址;如果不存在则会在缓存池中进行创建,创建完成后返回地址
注意:如果通过字串拼接所得内容和某个字串内容一致,但是地址不同

四  装箱/拆箱:

值类型自动转换成它对应的类类型 -autoboxing 、类类型自动转成它所对应的值类型 -unboxing
装箱。如: Integer a = 9;
将一个对像自动转成基本类型就叫拆箱 int c = new Integer(9);
java.lang.Object
所有 Java 类都直接或者间接的继承自 Object 类,那么 Object 中的方法也是其他所有类都拥有的
Object 类中的常用方法
getClass 方法用于获得当前对象的类型
直接输出一个对象时,实际上默认输出的是该对象 toString() 方法的返回值。所有的 Java 类中都有这个方
法,因为 Java 类都直接或者间接的继承于 Object 类,而 Object 类中定义了 toString 方法。为了实现用户
自定义输出格式,允许在类中覆盖定义 toString 方法
比较两个字符串是否相等,能用 “==” 吗?
Java 中的约定:重写 equals() 方法必须重写 hasCode() 方法
hashCode() 方法返回一个整形数值,表示该对象的哈希码值。
hashCode() 具有如下约定:
1). Java 应用程序程序执行期间,对于同一对象多次调用 hashCode() 方法时,其返回的哈希码是相同
的,前提是将对象进行 equals 比较时所用的标尺信息未做修改。在 Java 应用程序的一次执行到另外一次
执行,同一对象的 hashCode() 返回的哈希码无须保持一致;
2). 如果两个对象相等(依据:调用 equals() 方法),那么这两个对象调用 hashCode() 返回的哈希码也必
须相等;
3). 反之,两个对象调用 hasCode() 返回的哈希码相等,这两个对象不一定相等。
Integer k1 = 129 ;
Integer k2 = 129 ;
System . out . println ( k1 == k2 ); //false ,因为缓存只缓存 -128 127 之间的数据
String s1 = "abc" ;
String s2 = "abc" ;
String s3 = new String ( "abc" ); // 这里会创建 2 个对象 , 一个在缓存池中,一个是 new 导致的新创建
对象
System . out . println ( s1 == s2 ); //true
System . out . println ( s1 == s3 ); //false
即严格的数学逻辑表示为: 两个对象相等 <=> equals() 相等 => hashCode() 相等。因此,重写 equlas() 方法必须重写hashCode() 方法,以保证此逻辑严格成立,同时可以推理出: hasCode() 不相等 => equals()不相等 <=> 两个对象不相等。
可能有人在此产生疑问:既然比较两个对象是否相等的唯一条件(也是冲要条件)是 equals ,那么为什 么还要弄出一个hashCode() ,并且进行如此约定,弄得这么麻烦?
其实,这主要体现在 hashCode() 方法的作用上,其主要用于增强哈希表的性能。
以集合类中,以 Set 为例,当新加一个对象时,需要判断现有集合中是否已经存在与此对象相等的对象, 如果没有hashCode() 方法,需要将 Set 进行一次遍历,并逐一用 equals() 方法判断两个对象是否相等,此 种算法时间复杂度为o(n) 。通过借助于 hasCode 方法,先计算出即将新加入对象的哈希码,然后根据哈 希算法计算出此对象的位置,直接判断此位置上是否已有对象即可。(注:Set 的底层用的是 Map 的原理 实现) 在此需要纠正一个理解上的误区:对象的hashCode()返回的不是对象所在的物理内存地址。甚至也不一
定是对象的逻辑地址, hashCode() 相同的两个对象,不一定相等,换言之,不相等的两个对象,
hashCode() 返回的哈希码可能相同。
protected void finalize() ; finalize 方法主要与 Java 垃圾回收机制有关。首先我们看一下 finalized
法在 Object 中的具体定义: protected void finalize() throws Throwable { }
我们发现 Object 类中 finalize 方法被定义成一个空方法,为什么要如此定义呢? finalize 方法的调用时机 是怎么样的呢?
首先, Object 中定义 finalize 方法表明 Java 中每一个对象都将具有 finalize 这种行为,其具体调用时机在: JVM准备对此对形象所占用的内存空间进行垃圾回收前,将被调用。由此可以看出,此方法并不是由我 们主动去调用的(虽然可以主动去调用,此时与其他自定义方法无异)。

五   多态性:

多态性是发送消息给某个对象,让该对象自行决定响应何种行为。通过将子类对象引用赋值给超类对象
引用变量来实现动态方法调用
public class Test1 {
public static void main ( String [] args ) {
Fa cc = new Fa ();
// 调用的是一个名称为 pp 的方法,但是参数不同执行的处理不同
cc . pp (); //Fa...pp
cc . pp ( 12 ); //Fa.pp(int)
}
}
class Fa {
public void pp (){
System . out . println ( "Fa...pp" );
}
public void pp ( int k ){
System . out . println ( "Fa.pp(int)" );
}
}​​​​​​​
多态性通过允许同一界面指定一类动作减少了程序的复杂度,编译器工作就是选择适用于各个情况的特 定动作,而程序员则无须手动进行选择,使用者仅仅是记得以及利用这个统一的界面
多态形成的三个必要条件:
有继承,父类定义方法,子类重写方法
父类的引用指向子类的对象
可以使用参数传递时多态,也可以直接创建对象时多态
多态可以用 三个定义和两个方法 来总结。三个定义分别是父类定义子类构建、接口定义实现类构建和抽 象类定义实体类构建,而两个方法分别是方法重载和方法重写。
多态分为两种:
编译时多态:方法的重载
运行时多态: JAVA 运行时系统根据调用该方法的实例的类型来决定选择调用哪个方法则被称为运行 时多态
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值