}
// 不可变类定义要求:2.不对外提供实例变量set方法
public int getNum() {
return num;
}
public String getDesc() {
return desc;
}
public Person getPerson() {
// 不可变类定义要求:5.如果实例变量类型是可变类类型,则不能直接将该实例变量的原始值提供出去,而是创建一个备份值提供出去
return new Person(person.getName(),person.getAge());
}
@Override
public String toString() {
return “FinalTest2{” +
“num=” + num +
“, desc='” + desc + ‘’’ +
“, person=” + person +
‘}’;
}
}
// Person类是一个可变类
class Person{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return “Person{” +
“name='” + name + ‘’’ +
“, age=” + age +
‘}’;
}
}
class Main2{
public static void main(String[] args) {
FinalTest2 finalTest2 = new FinalTest2(10, “desc”, new Person(“qfc”, 10));
System.out.println(finalTest2);
finalTest2.getPerson().setAge(60);
finalTest2.getPerson().setName(“qfc father”);
System.out.println(finalTest2);
}
}
缓存不可变类实例
package finalTest;
import java.util.Arrays;
// 缓存不可变类实例
// 1.定义一个不可变类
public class CacheUnChangedTest {
private final String name;
private final int age;
// 4.创建一个容量合适的容器,来存储不可变类实例
private static CacheUnChangedTest[] cArr = new CacheUnChangedTest[3];
// 5.定义一个位置变量,来标记容器中实例存储的最新位置
private static int pos = 0;
// 2.私有化不可变类构造器
private CacheUnChangedTest(String name, int age) {
this.name = name;
this.age = age;
}
// 3.提供一个公有方法对外提供新创建或缓存过的实例
public static CacheUnChangedTest getInstance(String name,int age){
// 6.判断需要提供的实例是否已经创建过了?如果创建过了,则从容器中取出提供;如果未创建,则创建一个新的实例,加入到容器中,并提供出去
// 定义对外提供的实例变量 c
CacheUnChangedTest c = null;
System.out.println(“缓存池中的实例:”+Arrays.toString(cArr));
// 定义flag来标识外部需要的实例是否已经创建过,true表示已经创建过,false表示没有创建过
boolean flag = false;
// 遍历容器元素,判断外部需要的实例是否已经缓存过了?
for (CacheUnChangedTest cacheUnChangedTest : cArr) {
// 具体判断实例相同的标准可以自己定,只要在缓存池cArr中发现了相同的实例,则终止循环,直接提供缓存池中的实例给外部,而不需要创建新的实例
if (cacheUnChangedTest != null && cacheUnChangedTest.getName().equals(name) && cacheUnChangedTest.getAge() == age) {
flag = true;
c = cacheUnChangedTest;
break;
}
}
// 如果外部需要的实例还没有被创建过
if (!flag) {
// 则直接创建一个新的实例
c = new CacheUnChangedTest(name,age);
// 并且存入缓存池中
if (pos != cArr.length) {
// 如果缓存池还没有存满,则继续存
cArr[pos++] = c;
} else {
// 如果换存储已经存满了,则将位置变量变为0,从头开始重新覆盖存
pos = 0;
cArr[pos] = c;
}
}
return c;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return “CacheUnChangedTest{” +
“name='” + name + ‘’’ +
“, age=” + age +
‘}’;
}
}
class Main3{
public static void main(String[] args) {
CacheUnChangedTest c1 = CacheUnChangedTest.getInstance(“qfc”,18);//缓存池中的实例:[null, null, null]
CacheUnChangedTest c2 = CacheUnChangedTest.getInstance(“zyx”,19);//缓存池中的实例:[CacheUnChangedTest{name=‘qfc’, age=18}, null, null]
CacheUnChangedTest c3 = CacheUnChangedTest.getInstance(“孙悟空”,18);//缓存池中的实例:[CacheUnChangedTest{name=‘qfc’, age=18}, CacheUnChangedTest{name=‘zyx’, age=19}, null]
CacheUnChangedTest c4 = CacheUnChangedTest.getInstance(“qfc”,18);//缓存池中的实例:[CacheUnChangedTest{name=‘qfc’, age=18}, CacheUnChangedTest{name=‘zyx’, age=19}, CacheUnChangedTest{name=‘孙悟空’, age=18}]
System.out.println(c4 == c1);//true
CacheUnChangedTest c5 = CacheUnChangedTest.getInstance(“zyx”,19);//缓存池中的实例:[CacheUnChangedTest{name=‘qfc’, age=18}, CacheUnChangedTest{name=‘zyx’, age=19}, CacheUnChangedTest{name=‘孙悟空’, age=18}]
System.out.println(c5 == c2);//true
CacheUnChangedTest c6 = CacheUnChangedTest.getInstance(“zyx1”,18);//缓存池中的实例:[CacheUnChangedTest{name=‘qfc’, age=18}, CacheUnChangedTest{name=‘zyx’, age=19}, CacheUnChangedTest{name=‘孙悟空’, age=18}]
CacheUnChangedTest c7 = CacheUnChangedTest.getInstance(“qfc”,18);//缓存池中的实例:[CacheUnChangedTest{name=‘zyx1’, age=18}, CacheUnChangedTest{name=‘zyx’, age=19}, CacheUnChangedTest{name=‘孙悟空’, age=18}]
System.out.println(c7 == c1);//false
}
}
思考题
===
1.Java是否允许访问未初始化的final成员变量?或者请看下面代码的运行结果是什么?(final设计缺陷,好玩的题目)
public class Main5 {
final int a;
{
test();
a = 6;
System.out.println(a);
}
private void test() {
System.out.println(a);
}
public static void main(String[] args) {
Main5 main = new Main5();
}
}
这个题目是在李刚老师的疯狂java讲义上看到的。(第五版的181页)
我们一般理解final修饰的成员变量如下:
final修饰的成员变量,系统不会自动初始化,而需要程序员显式初始化。而在变量初始化之前,是不建议使用该变量的。
但是java还有一个规则:
Java允许在final成员变量显式初始化前,通过方法访问final成员变量。
那么在final成员变量显式初始化之前,final成员变量理论上没有值的。但是经过方法访问后,final成员变量的值就会变成0.
且还能被重新赋值。
按照李刚老师的结论,这是final设计的缺陷。违反了final的初衷:1.final修饰的成员变量只能显式初始化 2.final修饰的成员一旦初始化,就不能再次赋值。
所以:李刚老师建议:在final成员变量显式初始化之前,不要访问final成员变量。
2.final修饰基本类型变量和引用类型变量的区别?
我们知道:final修饰的变量一旦初始化后,就不能二次赋值了。
这个结论可以换种方式说:
举例:
final 变量类型 变量名 = 变量值;
初始化就是:增加一个指向,即(变量名)指向(变量值)
被final修饰意味着:指向就不能再改变了。
对于基本类型而言,它们的(变量值)就是字面量,字面量是无法改变的。所以“指向”无法改变,“变量值”无法改变,则基本类型变量被final修饰后就是一个固定常量。
对于引用类型而言,它们的(变量值)是对象,对象是有内容的(即对象的成员变量),final只能约束“指向”无法改变,无法约束“变量值”的内容不能改变。则引用类型被final修饰后,指向的对象的内容是有可能改变的。
如何保证对象的内容不被改变?那么就需要将对象的类型定义成不可变类。
3.什么是宏变量?
宏变量的定义:
1.变量被final修饰
2.变量在声明时被初始化
3.变量指向的值,在编译期就能确定
宏变量的作用:
编译器可以在编译期将使用宏变量的地方全部替换成变量值。
4.final修饰的方法是否可以重载?
final修饰的方法有如下特点:
1.不能被子类重写
2.不能再被abstract修饰
所以final修饰的方法只是限制了父子类之间方法重写。
方法重载指:在同一个类中,方法名相同,方法的形参不同(形参个数,形参类型,形参顺序不同)的方法。方法重载与访问权限修饰符,方法返回值类型无关。
final修饰的方法可以重载。重载的方法可以是非final的。
如下代码是针对final方法的重载:
public class FinalMethodReLoadTest {
final void test(String a,int b,Double d){
}
void test(Double daa,String abc,int bca){
}
final String test(int a){
return “”;
}
}
5.final类和不可变类的区别?
被final修饰的类的特点:
1.不能派生子类,即不能被其他类继承
2.不能被abstract修饰,即不能定义为抽象类
不可变类的概念是:
不可变类的对象的实例变量不会改变。
所以两者是不同的概念。很多人错误的理解final类就是不可变类,这是对不可变类的概念不清晰导致的。
6.不可变类的(实例变量)【类型】如果是(可变类类型),那么如何保证这个(可变类类型)的(实例变量)指向的对象内容不会变更?
两种方案:
1.把这个实例变量的类型的类定义改成不可变类模式。
2.通过一个备份值来保证(可变类类型)实例变量的指向对象不会被改变。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
结尾
正式学习前端大概 3 年多了,很早就想整理这个书单了,因为常常会有朋友问,前端该如何学习,学习前端该看哪些书,我就讲讲我学习的道路中看的一些书,虽然整理的书不多,但是每一本都是那种看一本就秒不绝口的感觉。
以下大部分是我看过的,或者说身边的人推荐的书籍,每一本我都有些相关的推荐语,如果你有看到更好的书欢迎推荐呀。
Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
[外链图片转存中…(img-ZBNF4rsA-1713486009163)]
[外链图片转存中…(img-4pc7Czud-1713486009164)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
[外链图片转存中…(img-5BJHR2so-1713486009164)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
[外链图片转存中…(img-WRrZ5idS-1713486009165)]
结尾
正式学习前端大概 3 年多了,很早就想整理这个书单了,因为常常会有朋友问,前端该如何学习,学习前端该看哪些书,我就讲讲我学习的道路中看的一些书,虽然整理的书不多,但是每一本都是那种看一本就秒不绝口的感觉。
以下大部分是我看过的,或者说身边的人推荐的书籍,每一本我都有些相关的推荐语,如果你有看到更好的书欢迎推荐呀。