Java语法手册 三(面向对象)
Java面向对象编程:
面向过程 or 面向对象
二者都是一种思想,面向对象是相对于面向过程而言的。
- 面向过程,强调的 是功能行为,以函数为最小单位,考虑怎么做。
- 面向对象 将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。 面向对象更加强调运用人类在日常的思维逻辑中采用的思想方法与原则,如 抽象、分类、继承、聚合、多态等。
面向对象的三大特征:
- 封装 继承 多态
类和对象
类:
- 类是对一类事物的描述,是抽象概念 类是 对象的类型; 人就可以理解为是一个类;
- 类的实例是对象将拥有的类的 特征(属性) 行为(方法);
- 类的属性:
对象所拥有的静态特征, 称为类的属性:
人类人都有: 姓名 身高 体重...
- 类的行为:
对象执行的操作动态特征, 称为类的方法:
人都可以吃饭, 唱歌..
对象:
- 程序中: 对象是实际存在的某类事物的个体 , 因此也是客观事物的一个实体。
小明,小红就是人类的对象
- 对象具有:静态特征/动态特征,分别称为对象的 属性/行为方法; 由类实例化创建 new)
类和对象的关系:
- 类是拥有相同行为特征对象的一个抽象概念,而对象是类这个抽象概念中事实存在的个体
- 类和对象的关系 就像 摸具和模型: 可以根据 一个摸具 制造出 很多相同 的模型; 但后面 颜色…还可以更改,表示不同的对象…
- 结论: 类是对象的抽象,对象是类的实例; 类 是 对象 的 类型;
JAVA是面向对象的语言:
Java的类声明:
Java中的类是将现实世界中的概念模拟到计算机中 在Java中创建一个类 要使用: class,一个类名,一对大括号{};
类的属性:
在类主体中定义变量来描述类的静态特征(属性) 这些变量称为类成员变量;
在方法中的变量称为局部变量
编写类的方法:
在类中 定义方法描述类所据有的行为(类的成员方法) 定义方法语法:
代码语言:javascript复制1.方法名称 2.方法返回值类型 3.方法主体
访问修饰符 返回值类型 方法名(){
//方法体:
//进行 操作运行的代码
}
访问修饰符: //public...访问修饰符限制了访问该方法的范围
返回值类型: //方法执行之后的返回结果的类型(基本类型/引用类型),也可以没有返回值 void; 必须得填!
方法名: //有意义的名字方便调用
//注意:命名规范(骆驼命名法,首字符小写,其它单词首字母大写)
注意:
//方法体放在一个大括号中{} 方法体就是一段程序代码,完成一定的工作
//方法名主要在调用这个放法时使用,在java中 一般采用骆驼式命名法
//方法执行后可能会返回一个结果该结果的,类型称为返回值类型,使用return 返回值;
//如果方法不返回结果返回值类型默认: void;(没有返回值类型)
//return 作用: 1.跳出方法 2.如果方法 有返回值 这个值 放在 return 后面;(给 方法返回一个值)
//return 表达式; 给方法返回一个值(表达式); 表达式 类型要与 方法返回值 类型一致;
使用类/创建对象:
代码语言:javascript复制类的 作用就是 创建对象,由类生成 对象,称为类的实例化 过程
一个 实例 就是一个对象
一个 类可以生成多个对象
语法:
类名 对象名 = new 类名();
//new 创建对象;
//使用对象.调用属性/方法
语法:
对象名.属性 //引用对象属性
对象名.方法名(); //引用对象方法
//通过 对象名 "." 操作
扩展:
使用对象 .点调用类属性
如果类属性未赋值 对象.调用属性 取到其 变量类型的 默认值!!
int 0
String null
char 'u0000'
boolean false
double 0.0
... ...
命名规范:
骆驼(Camel)命名法: 首字母小写后面的单词首字母大写; eg: showCenter userName.... (定义 属性/方法)
帕斯卡(Pascal)命名法: 每个单词首字母大写; eg: School... (定义 类)
匿名类:
匿名类是内部类的一种…实际开发中使用不多,但是源码可能会见到!
匿名对象:
// 简单理解, 类声明对象就是为了调用 类中的属性和方法; 进行操作;
// 匿名对象就是没有对象即: new 类().属性/方法();
// 并没有创建对象调用了 类的方法/属性 的操作;
// 很少使用,好处用完自动回收内存空间~
使用场景: 多线程...
匿名子类:
// Java 存在继承,子类继承父类。
// 匿名子类和匿名对象一样,一般只使用一次用完即回收了的;
// 假设: abstract class A{ //抽象类A };
// 即: A a = new A(){ //重写A类抽象方法,间接也继承了A类属性/方法,也可以自定义此类的特有属性/方法(用于内部访问) }; 抽象类是不能new 实例的,即这里就是在表示一个 匿名类了;
// 创建出对象a 就是这个匿名类的实例了,即这个类是没有名字的借用了父类名,a可以调用: { 中的属性/方法 } 还有父类的非抽象公开方法/属性也可以的;(和普通类几乎无异)
// 虽然 匿名类,可以自定义方法/属性,但其对象接收类型是继承类父类/实现类。所以还是没办法访问(需要转换类型),但又因为你是匿名...所以直接凉凉...只能设置private 内部访问了;
匿名实现类:
// 和匿名子类类似;
// 假设存在接口: interface A{ } 即: A a = new A(){ .... };
面向对象的优点:
代码语言:javascript复制//与 人类 思维习惯一致
//信息隐藏,提高程序 可维护性,安全性;
//封装 实现了 模块化 和 信息隐藏 即 类的 属性/方法(行为) 封装在类中 保证了 对它们 修改 不会影响到其他对象 利与维护
//封装 使 在对象外部 不能随意访问 对象 属性/方法 避免外部 错误 对 它的影响 提高了安全性
//提高了 程序的 可重用性 一个类 可以 创建 多个对象实例 增加重用性
类的无参方法
在类中 定义方法 描述 类所据有的 行为(类的 成员方法)
定义方法语法:
代码语言:javascript复制1.方法名称 2.方法返回值类型 3.方法主体
访问修饰符 返回值类型 方法名(){
//方法体:
//进行 操作运行的代码
}
访问修饰符: //public...访问修饰符限制了访问该方法的 范围
返回值类型: //方法 执行之后的返回结果的类型(基本类型/引用类型) 也可以没有返回值 void;
方法名: //有意义的 名字 可以 方便调用 注意:命名规范 (骆驼命名法)
成员变量和局部变量:
类中可以定义:变量/方法 (成员) 在类方法中同样可以定义变量(局部)
代码语言:javascript复制成员变量:
在类中定义的变量,有访问修饰符
局部变量:
它的作用域主要定义在方法/{ } 因此只能在定义的方法/{ }使用,因此也就没有访问修饰符;
注意:
作用域不同:
局部变量 作用域 仅限于 定义它的 方法;
成员变量 作用域在 整个类内部 可见 所有成员方法都可以 使用 如果访问修饰符 允许还可以 在类外使用;
初始值不同:
成员变量 如果在 类定义中 没有 给它赋初始值 java 会给它一个 默认初始值;
局部变量 如果不赋值 系统不会默认赋值 因此 局部变量必须定义赋值后 再使用;
同一方法中 局部变量不可以同名 同类不同方法可以....;
局部变量 成员变量 可以有相同方法名 并且在 使用时 局部变量具有更高的 优先级; 程序遵循就近原则!
带参方法
在类中 定义方法 描述 类所据有的 行为(类的 成员方法)
代码语言:javascript复制1.方法名称 2.方法返回值类型 3.方法主体
访问修饰符 返回值类型 方法名(<参数列表>){
//方法体:
//进行 操作运行的代码
}
访问修饰符: //public...访问修饰符限制了访问该方法的 范围
返回值类型: //方法 执行之后的返回结果的类型(基本类型/引用类型) 也可以没有返回值 void;
方法名: //有意义的 名字 可以 方便调用 注意:命名规范 (骆驼命名法)
参数列表: //方法()括号中放参数类型, 用于指定方法内运行 需要使用的变量/数据进行操作; 又分为形参 实参;
形参: 出现在方法定义时,括号中的,只在当前方法中使用 (局部变量 占用栈空间方法结束就自动回收),用于方法的内部操作执行;
实参: 出现在调用方法时,实参的值传给形参,使其进行方法内部的操作执行,因此方法调用时实参不受影响;
//注意: 实参是 值类型/引用类型: 值类型传给形参值,实参不受影响。引用类型传地址实参受影响(String 特殊);
汇总:
代码语言:javascript复制方法是, 定义在类中, 是一种行为操作。 main 也是一种方法;
使用时候调用即可,方法内部可以调用其它方法 (当然也可以调用自己: 递归,要注意有 return/结束;不然死循环就出问题了)
同一个类可以之间相互调用,不同类声明对象调用 (注意访问修饰符……)
构造函数:
类 和 对象
类 (Class) 对象(Object)是面向对象的两个核心概念
- 类: 类是对某一类事务的描述是抽象概念上的定义
- 对象: 对象是实际存在的具体的事物个体
构造方法
构造函数,有的人又叫构造方法… 总之都是一个东西..
- 我们都知道使用类的属性 和 方法 来完成程序功能,首要任务就是将类进行实例化 类 对象名 = new 类();
- 假设创建 类对象ww 这种创建类实例的方法被称为构造函数;
- 类的构造函数是类的一种特殊方法;
特点:
代码语言:javascript复制1.方法名与类名相同
2.没有返回值
3.一般来说主要完成对象的初始化工作
4.构造方法可以 Private (封装) //但其他类就不能对这个类 进行初始化 所以不建议~(单例实例特殊~);
5.构造方法可以重载,根据参数不同可声明一个/多个构造函数; (一个类中无论如果必须有一个构造函数,无系统会默认提供一个无参的构造方法 有则使用定义的!)
注意: 构造函数没有返回值,并不是代表可以为void void表示返回值类型为空并不是没有返回值 so不可以是void ※
(如果在 JAVA 中构造函数加了 void 返回值并不会报错 而是成为和构造函数 / 方法名 相同的一个方法
重载overLoad
:
同一个类可以有相同的: 方法名? 答 : 可以! - o - 跌幅常理,不过确实可以!
代码语言:javascript复制※ 特点: (两同一不同)
1,方法名相同 ^^
2,同一类(或子类)!!
3,方法(参数列表)不同!
//正是参数不同才靠此区分方法!使用时系统也根据你调用的方法参数 类型 顺序 数量 来判段调用的方法;
说明:
和正常的方法其实变换无一,只是加了方法可以重载,一个类可以有相同方法名;(两同一不同)。
注意:
方法重载 ,同一类,同方法名 ,不同参数列表,称为方法重载 返回值/访问修饰符??(与返回值/访问修饰符无关)
扩:
// 可变个数形参方法:就是说参数向是一个数组 JDK5.0以前是数据表示 所以同时使用:可变参数类型int / int数组参数会报错; (重载参数类型一样 int举例)
访问修饰符 返回值类型 方法名( 数据类型...变量名 ){
//数据类型...变量名: 可变个数形参,表示给方法传参时候可以根据对应数据类型传入零个/多个同类型参数;
//方法内部使用时,变量名[0]第一个参数 变量名[1]第二个参数...相当于是一个便捷的数组一样;
//使用时,这种可变个数形参 作为参数一般放在最后且一个方法这可有一种;(否则编辑器不好分辨~)
//具体图: 可变型参数;
}
封装:
代码语言:javascript复制面向对象三大特征( 封装 继承 多态 ) 之一:
// 当我们创建一个 类对象后,我们可以通过: 对象.属性 方式对其赋值操作;
// 但如果,想要对,赋的值存在一些限制就要写 方法set内部进行判断; 而之后我们还是可以通过: 对象.属性 进行赋值所以一般给其设置: private(私有属性)
定义:
隐藏对象(类)属性,和实现细节,仅对外公开接口(方法); 控制在程序中属性的读取get(读) 和修改set(写) 的访问级别;
set(参数){ …… }; //封装通过set 给,类对象属性进行赋值操作,当然也可以对齐内部进行判断使其只能赋:合法值: 年龄不能是 负数;
扩:
// 也可以是不对外暴露的私有方法, 只是允许内部调用; 单例测试(构造函数 设置private后续~)……
// 我们对程序设计追求: 高内聚(类的内部数据操作细节自己完成,不允许外部干涉 ) / 低耦合(仅对外保留少量的方法用于使用 );
封装的体现需要权限修饰符来配合体现:
private
default(默认什么都不写即可!)
protected
public
Java中 this
代码语言:javascript复制// 可以理解为 this 是当前类对象; 可以调用 属性/方法/构造函数;
// 调用成员变量解决:成员变量 与 局部变量 同名的冲突;
// 类中构造函数:(图:this构造器 减少代码量冗余)
注意: this 对象内部值对自身的引用,所以 this只能调用 实例属性/方法,构造函数 (并不能调用静态的成员: static), this只能在方法中使用!!
继承:
继承的概念:
- 继承允许我们根据 一个类来定义另一个类, 使得创建和维护应用程序更加容易,同时有利于重用代码减少冗余,节省开发时间;
- Java中一个类可以继承,另一个类; 被继承的类 称为:“父类”/“基类” 继承其他类的类 称为:“子类”/“派生类”;
- 是面向对象,编程 一个非常重要的特性,子类 不仅 具有 自己类独有的成员,还具有父类成员;
- 继承要 符合 is a 的关系; eg: 卡车是汽车,卡车is a汽车;
继承的特性:
继承的传递性 :A继承B 类 B继承C A具有C类属性/方法; B是A父类 C是A间接父类;
继承的单根性 :一个子类不能同时继承多个类,只能继承一个类;
//java 中所有类都直接或间接的 继承了 Java.lang.Object 类 !
Java 继承关键字: extends实现java继承 A extends B (A类 继承 B类);
super 代表指对 父类对象的默认引用 (可以理解就是父类的一个实例对象) 因此不能访问父类的 类属性/方法(static)
注意: java 子类 继承 父类 属性/方法 (并不能继承 构造函数 只能调用)
可以通过 this 访问父类 属性/方法 (但不建议)建议 super 访问; // 使用this this会先在本类中找 属性/方法如果有掉自己的,没有才会去找父类的属性/方法;
子类中声明 构造函数 需要使用 super(); 调用相应的父类的构造函数 : super( 参数指定父类构造函数参数匹配 );//第一行表示(必须!!)
如不显示调用 则系统默认调用 父类无参构造函数 super(); !! 注意 前提父类是否存在无参!! this(); 是本类的构造函数不是父类!!
this 和 super 只能在方法中使用!! 且使用时只能 二选一;
访问权限: 级别 高 - 低
public (公共的): 都可以访问
默认 (不写即可): 本类 同包 可以访问
protected(保护的): 本类 同包 子类(不同包也可) 可以访问
private (私有的): 只允许本类访问
// 可以用来修饰类及内部结构: 类,属性,方法,构造函数,内部类
属性: 成员变量才可以设置访问权限; // 如果访问不成功: is not visible; 错误
重写:
代码语言:javascript复制子类重写父类方法: 子类不满足 父类的方法 子类可以对其修改 重写/覆盖 (overriding)
条件:
方法名相同
参数列表相同
返回值类型相同 (或是其类型子类: 父方法返回值Object 子重写方法返回值可以是 String )
重写的方法访问修饰符 权限大于 被重写方法! (子类重写父类的方法访问权限必须 >= 父类方法)
子类重写父类方法,抛出的异常类型,不能大于父类的异常类型;
注意:
子类 和 父类 方法重写: 方法名相同 参数列表相同... 与方法 重载 无关!!;
子类 和 父类的同名同参数的方法要么都是 非static(重写) 要么都是 static (已经不是重写了); 如果一个是 static一个不是则会报错;
JAVA抽象类和抽象方法: (当父类的方法,一定会被子类重写,那父类方法就不需要方法体了,可以定义成抽象方法,抽象类)
抽象类: 通常用来表示 (父类) 概念性类 eg: 动物/车/气体...
所以: 抽象方法也就没有方法体, 且必须存在抽象类中 (但 抽象类中也可以有 非抽象方法/属性 构造方法..)
抽象类也不能实例化,所以抽象类,一般都是父类; 但抽象类是存在构造函数的,便于子类实例化:super();
而: 子类 (非抽象类) 必须实现 父类(抽象类)的抽象方法!; 子类继承抽象类,必须实现其抽象方法;
所以: 不可以是 private final // 与抽象类概念冲突了,且编辑器会报错!
抽象方法: 需要被(非抽象)子类重写的方法,因此 访问修饰符不能是 private(会报错),不可以是 static(不是重写:且static可以通过类.调用而抽象方法并没有主体) final(不允许重写) 修饰!!
关键字: abstract (抽象)
抽象类: public abstract class 类{}; 抽象方法: public abstract void 方法名(); // 抽象方法没有方法主体哦~且类一定是抽象类/接口
多态:
代码语言:javascript复制字面意思:“多种形态”指统一操作,同一操作 用于不同对象时 可以有不同的处理,产生不同执行结果;
优点: 减少代码量,提高代码的可扩展性 和 可维护性
JAVA 实现多态:
父类 ww = new 子类(); 可以 声明 父类型 new 子类对象,调用重写的方法 ,因 不同的子类 对象 重写不同的方法主体 所以 输出结果根据new子类不同而不同 实现多态;
ww.方法(); //实现操作
注意:
子类到父类型转换: 父 o = new 子; (称: 向上转换)//完成多态操作,根据子类重写的方法new的子类不同, 对象.方法 就展示不同的效果; 当然子类中特有的方法 以父类型的对象是无法访问的啦!
父类到子类型转换: 子 o = (子)new 父; (称: 向下转换)//通过强转可以转成 对应的子类类型, 但对象调用方法时有可能会报错哦~ ,new 父 其本质是父类型对象强转成子类(不报错) 但它就不是子类!, 一般这种转换是结合:父 o = new 子; 子 o1 = (子)o; //强转
转换 类型 由 低到高系统会 自动/隐式 转换 eg: double = int; (称: 向上转换)
转换 类型 由 高到低系统需要 手动/显示式 转换 eg: int = (int)double; (称: 向下转换:会损失精度问题)
JAVA中强转失败系统会报错: ClassCastException 错误,影响程序操作, 所以 建议 使用 instanceof 进行判断后转换~
instanceof 运算符: 检查对象类型是否属于该类型!!
A对象 instanceof Object(类型); //成立 true 则 flase
instanceof 使用 时也必须符合 对象和类 是继承树 上下级关系 不然 编译 错误!!
实现多态条件:
1.继承的存在
2.重写的存在 注意:重写重写的是方法,并不是属性. 子类 父类都有一个属性id; 调用时是根据你的对象类型调用你的属性及值, 而不会因为你 new谁而决定哦!
3.父类 引用变量 指向子类对象(子类 到 父类的类型转换) 父类 ww = new 子类();
多态是编译时行为,还是运行时行为/根据new的子类不同调相同方法产生不同结果: 运行时;(图:多态运行时 多态虚方法 重载和重写)
接口:
代码语言:javascript复制什么是接口:
生活中: 接口是一套规范 USB
软件中: 同样是一套规范和标准,可以约束 类 的行为。
接口 可以是一种 特殊的"抽象类"
抽象类 利于代码复用 (继承,重写..)
接口 利于代码 维护/扩展 (接口可以多继承)
接口: 一般表示一种能力 一种程序方面的扩展
Java 是单继承 接口是多继承的 且 是抽象方法 限制了类必须实现方法 (多态的一种)
JAVA接口:
1.接口中的属性都是,全局静态常量,且定义常量时必须赋予初始值否则编译错误;(静态常量: 接口不能实例化)
2.接口中的所有方法都是 抽象方法 (抽象方法 子类非抽象类 必须实现方法)
Jdk1.7: ......
Jdk1.8: 之后接口中可以存在:static修饰的方法了; 且可以给方法像,属性默认值一样:声明默认方法主体;
//当一个接口,有n个类实现了,那么在添加一个抽象方法时候,n多个实现类就会报错......
public static void 方法(){ //方法主体 }; //与普通静态方法不一样,不能通过接口实现类对象.调用,只能通过 接口名.调用;
public default void 方法(){ //方法主体 }; //默认方法,实现类,可以选择重写/不重写. 类可以实现多个接口,当存在相同默认方法时:需要重写一次覆盖所有; 默认方法与继承类的方法重名,优先用父类的;
Jdk1.9: 接口中允许有私有方法:
private void 方法名(){ }; //解决多个默认方法之间,重复代码的问题;
private static void 方法名(){ }; //解决多个静态方法之间,重复代码的问题;
3.接口不是类,因此: 不能声明构造函数 不可以实例化;
4.接口之间 可以extends 实现继承: 一个接口可以继承多个接口,但类不能继承接口 (接口继承多个接口间逗号 分隔)
5.类可以继承一个类,实现接口(多个接口"," 逗号分隔 必须实现接口所有方法,否则,定义为抽象类...)
6.接口没有静态代码块.....
JAVA 定义接口
public interface 接口名A{ } //class 换成 interface 它不是类
public interface 接口A extends 接口,接口..{ } //接口继承接口 多个,逗号分隔
public class extends 继承父类 implements 接口,接口...{ } //类 继承 类 ,implements 实现接口,多个接口逗号分隔
static 修饰符:
代码语言:javascript复制static 静态的,可以修饰: 属性,方法,代码块,内部类 (static修饰的都是通过类加载而加载的.....);
使用static修饰属性:称为静态属性:static 基本数据类型 属性名;
// 类中属性(成员变量),按是否 static 修饰,又分为:静态变量(类变量) 或 非静态属性(称:实例变量);
(局部变量不可以static修饰,..因为static是类加载过程实现的.)
实例变量:
我们创建多个类对象,每个对象都有一套,类中的非静态属性;当修改其中一个对象中 的,非静态属性时,不会导致改变其它对象中的属性值;
静态变量:
我们创建多个类对象,多个对象共享同一个静态变量,当通过某一个对象修改静态变量时,会导致其它对象调用此静态变量的值是修改的;
// static 修饰的变量属于这个类所有,这个类创建的所有对象共同使用一个 static变量!!
// (static修饰的变量不是存在堆中,而是方法区....)
// 静态变量随着类加载而加载,比对象创建要早(对象还要new);
// 所以可以通过: 类.静态变量 方式进行调用使用,由于类只加载一次,则静态变量在内存中只占用一份;
// 属性可以被多个对象,所共享的不会随着对象不同而不同的可以设置 static修饰
使用static修饰方法:称为静态方法(反之:实例方法): public static void ff(){ //代码块 }; //main也是静态方法
// 静态方法: 只能调用静态的属性/静态方法(或通过创建对象.方式来调用实例方法/实例属性)
// 静态方法中不能使用 this关键字/super关键字:
this是指当前对象,而static方法,类加载先于任何实例对象;
矛盾(所以static也不可以修饰构造函数:构造函数的 super();/this();默认首行初始化.... );
// 实例方法: 既可以调用非静态方法/属性,也可以调用静态方法/属性;
// 操作静态属性的方法,通常设置static, 有一些工具类,中方法也可以设置成 static 修饰;方便调用
方法里不可以定义 static变量所以类变量不能是 局部变量;
java中类属性/类方法可以通过: 类名/对象 . 访问!而实例属性/实例方法只能同过对象 . 访问!
代码块(Code block):
代码语言:javascript复制代码块(Code block): Java中使用{ }括起来的代码被称为代码块!
局部代码块
语法: { ... }
方法中出现 { }
相当于 方法中 一个小方法,可以限定变量的使用范围(生命周期),及早释放,提高代码利用率;
构造代码块(非静态代码块)
语法: { ... }
类中出现 { } 实例对象时触发 优先于构造函数; (类每: new 类(); //每创建对象时就调用一次)
构造代码块与构造函数的区别:
构造代码块是给所有对象进行统一初始化,而构造函数是给对应的对象初始化.
因为构造函数是可以多个的,运行哪个构造函数就会建立什么样的对象,但无论建立哪个对象,都会先执行相同的构造代码块。
也就是说,构造代码块中定义的是不同对象共同的初始化内容。
静态代码块
在类中出现, static修饰代码块: 常用于给类进行初始化,在加载时候最先执行,且静态代码块 类加载过程只执行一次;
static{ //代码主体 };
//一个类中可以有多个static代码块,逐个执行类加载过程中执行最先执行;
//关于继承: 代码块中可以调用: 属性/方法; 注意静态方法/属性 非静态方法/属性;
同步代码块: 解决多线程问题的...下面↓↓
Synchronized (英: C克瑞奈斯)(中译: 同步)
同步代码块指的是被Java中Synchronized关键词修饰的代码块,在Java中,Synchronized关键词
不仅仅可以用来修饰代码块,与此同时也可以用来修饰方法,是一种线程同步机制
被Synchronized关键词修饰的代码块会被加上内置锁。
需要说明的是Synchronized同步代码块是一种高开销的操作,因此我们应该尽量减少被同步的内容
在很多场景,我们没有必要去同步整个方法,而只需要同步部分代码即可,也就是使用同步代码块(JDK源码中有很多应用)
final常量修饰符:
代码语言:javascript复制final常量修饰符:
常量: 在程序运行过程中不会发生变化 ,只能被引用,不能被重新赋值,只能在定义时修改其值;
final 修饰类 不能被继承/继承它类:final class 类名{ } // 则类中的所有方法都被隐式设置成了 final修饰,类都不继承了,又怎么重写? 所以也不可以和 抽象类 abstract/接口 interface在一起!
//比如: System类 String类! StringBuffer类!
final 修饰方法 不能重写: private final 返回值类型 方法名(){ };会报错! // 子类继承父类重写方法// final表示方法不能重写即: 可以继承,但定义了 private 方法就不能被继承了因此更不会被重写所以存在冲突……可以不用设置 private;
final 修饰变量 不可以再次赋值: static final 数据类型 变量名 = 值;
final 修饰属性,赋值方法: 显示初始化 静态代码块 代码块初始化 构造器初始化!
// Final可以在方法内 也可以作为形参使用! `估计不常用!`
// 全局常量(声明赋值/构造函数赋值,赋值之后值就无法修改,但如给其赋值时候就使用: rand.nextInt(10); //0—10内随机整数赋值 之后在类对象调用就不能确保这是值一致……)static修饰使每个类对象常量值一样(访问修饰符随意)
// 成员常量随意:方法内不能 static修饰,赋值一次就不可以修改了^^;
注意: fianl 修饰引用类型,引用类型,地址值不能修改!! eg: fianl A 对象名 = new A(); 之后 对象 不可以在 new A();//改变了引用地址值会报错!但对象.属性的内部值不会,不是改变地址值了;
fianl 修饰基本数据类型 值本身不能修该,(变量名通常所有字母大写 单词间 _ 分隔)
//JVM/java应用 会缓存final 的变量因此性能高~