s1.a = 1;
System.out.println(s1.a);//1
StaticTest s2 = new StaticTest();//构造器执行
s2.a = 2;
System.out.println(s1.a);//2
System.out.println(s2.a);//2
System.out.println(“====================================”);
//静态内部类,枚举类不能用类的实例名访问,只能用类来访问
System.out.println(StaticTest.Season.SUMMER);//SUMMER
//System.out.println(s1.Season.SUMMER);//Expected class or package
System.out.println(StaticTest.Inner.age);//18
//System.out.println(s1.Inner.age);//Expected class or package
}
}
static成员在继承中的表现
package staticTest;
public class Father {
public static String desc = “Father 静态变量desc”;
public static void info(){
System.out.println(“Father 静态方法info”);
}
public static void test(){
System.out.println(“Father 静态方法test”);
}
}
class Child extends Father {
// 子类实例方法不能重写父类静态方法(即使满足方法重写要求)
// Instance method ‘test()’ in ‘staticTest.Child’ cannot override static method ‘test()’ in ‘staticTest.Father’
// public void test(){
// System.out.println(“Child 实例方法重写父类方法”);
// }
// 子类定义了一个和父类相同的静态方法,只会对父类静态方法的隐藏,不会发生方法重写
// 即子类调用test方法,只会体现子类方法行为,不会体现父类方法行为,因为子类静态方法会再子类的方法区的静态域中开辟一个新内存去存储,和父类的静态方法没有关系
public static void test(){
System.out.println(“Child 静态方法test”);
}
// 另外子类定义的和父类相同的静态方法也不会体现多态性,详情间Main3测试
}
class Test {
public static void main(String[] args) {
// 被子类继承的静态成员,既可以通过子类名调用,也可以被子类实例调用
System.out.println(Child.desc);//Father 静态变量desc
Child.info();//Father 静态方法info
Child child = new Child();
System.out.println(child.desc);//Father 静态变量desc
child.info();//Father 静态方法info
System.out.println(“====================================”);
// 被子类继承的静态变量,并没有在子类方法区共享域中开辟新内存copy,而是子类直接访问的父类静态变量
// 下面测试可以发现,子类修改了继承的静态变量,父类的被继承的静态变量值也做了相同修改
child.desc = “子类修改了desc”;
System.out.println(child.desc);//子类修改了desc
System.out.println(Father.desc);//子类修改了desc
System.out.println(“====================================”);
// 子类自定义的相同声明静态方法会隐藏对父类静态方法,子类调用该静态方法总是表现子类行为。
Child.test();//Child 静态方法test
// 子类自定义的和父类相同声明的静态方法,不会体现多态性
Father father = new Child();
// 按照多态性,父类引用指向子类对象,则父类引用调用被重写的方法时,总是表现子类方法行为
// 但是静态方法没有体现多态性
father.test();//Father 静态方法test
}
}
单例类的实现
懒汉式
public class LazyMode {
private static LazyMode lazyMode = null;
private LazyMode() {
}
public static LazyMode getInstance(){
if (lazyMode != null) {
lazyMode = new LazyMode();
}
return lazyMode;
}
}
class Main{
public static void main(String[] args) {
LazyMode lazyMode = LazyMode.getInstance();
LazyMode lazyMode1 = LazyMode.getInstance();
LazyMode lazyMode2 = LazyMode.getInstance();
System.out.println(lazyMode==lazyMode1);
System.out.println(lazyMode1==lazyMode2);
}
}
饿汉式
package staticTest;
public class HungerMode {
private static HungerMode hungerMode = new HungerMode();
private HungerMode(){
}
public static HungerMode getInstance(){
return hungerMode;
}
}
class Main2{
public static void main(String[] args) {
HungerMode hungerMode = HungerMode.getInstance();
HungerMode hungerMode1 = HungerMode.getInstance();
HungerMode hungerMode2 = HungerMode.getInstance();
System.out.println(hungerMode==hungerMode1);
System.out.println(hungerMode1==hungerMode2);
}
}
思考题
===
1.为什么类成员(静态成员)不能访问实例成员(非静态成员),而实例成员(非静态成员)可以访问类成员(静态成员)?
因为类成员的生命周期和实例成员的生命周期不一致。
类成员随类的加载而加载,类成员加载完成后,类还没有产生任何实例,所以类成员无法访问实例成员。
而实例成员随着对象的创建而加载,而创建对象前,对象的类已经完成记载,所以类成员已经存在了,所以实例成员可以访问到类成员。
2.静态方法中是否可以使用this,super关键字?
不可以
this指代当前类的实例
super指代当前类的父类实例
两者都是实例相关,可以看成是实例成员,非静态成员
而静态成员是不能访问非静态成员的。
所以静态方法中不能使用this,super关键字
3.类的所有成员都可以被static修饰吗?
不是
类的构造器不能被static修饰。
为什么类的构造器不能被static修饰呢?
我们首先要理解下构造器的根本作用是什么?
构造器的根本作用是为对象的成员变量进行初始化。
我们知道一般构造器使用如下:
new 构造器(参数a,参数b){
this.a = a;
this.b = b;
}
其实在执行构造器的方法体之前,系统已经得到new命令,创建好了一个对象,且对象中的成员变量已经完成了默认初始化。
而构造器的作用就是在对象成员变量默认初始化的基础上,再进行一次自定义初始化。
所以构造器的根本作用没有说是创建对象,而是为对象的成员变量初始化。
但是对象的成员变量既包括实例变量,也包括类变量,那么如果我们把构造器用static修饰了,
根据static修饰的特点,构造器就是静态成员了,静态成员不能访问非静态成员,
那么构造器的根本作用对成员变量初始化的工作就完成不了了。因为它无法对实例变量初始化。
4.父类的静态成员可以被子类继承吗?和实例成员的继承区别是什么?
父类的静态成员可以被子类继承。
但是和实例成员的继承不一样。
子类创建对象时,会在堆内存中开辟一个对象空间,在对象空间中会将本类的实例成员,和父类继承过来的实例成员分别存储。此时,从父类继承过来的成员 和 父类本身已经没有联系了,即子类修改继承过来的实例成员,不会影响父类本身的实例成员。
或者换一种思维:
实例成员时属于实例的。而子类实例和父类实例时两个实例,互相不会有牵扯的。所以继承给子类的实例成员,不再和父类实例有任何瓜葛。
而对于静态成员的继承:
我们直到类的静态成员存储方法区的静态域中,(而不是存储再堆中),而子类继承父类的静态成员后,不会再子类的方法区的静态域中开辟一个新内存区copy父类静态成员,而是直接引用父类的方法区的静态域的静态成员。所以子类对于继承过来的静态成员的修改会直接体现到父类的静态成员中。
或者换一种思维:
静态成员只属于类本身,全内存中只有一份。所以子类不能再开辟一个copy静态成员内存区,而是需要直接引用到父类静态成员。
5.父类的静态方法可以被子类重写吗?
父类的静态方法不能被子类重写。或者说重写没有意义。
我们回忆一下方法重写的规则:
发生在父子类间,子类重写父类方法
1.方法名,方法形参列表相同
2.子类的(方法返回值类型,方法抛出的异常)要小于父类的
3.子类的(访问权限修饰符)要大于父类的
可以看出方法重写规则并没有说static的要求。但是重写的基本要求是继承,是父子类,是父子类的方法区中各自的方法。是一个父类方法,一个子类继承的方法,是两个方法间的重写。
即子类重写继承自父类的方法后,父类本身的行为不会改变。
而静态方法的继承不同于实例方法的继承,子类不会copy父类静态方法到自己的静态域中,而是直接引用父类静态域。所以父子类间只有一个父类方法去静态域中静态方法。
所以如果允许子类可以重写父类静态方法的话,父类的行为也会被改变。
6.子类中定义的和父类相同的静态方法,是方法重写吗,是否可以体现多态性?
子类中定义了和父类静态方法相同的静态方法,依然不是方法重写。
只是子类自己新定义的静态方法而已,和父类的静态方法没有关系。
而有些同学会被一个例子迷糊住:
class Father{
public static void test(){
System.out.println(“Father test”);
}
}
class Child extends Father{
public static void test(){
System.out.println(“Child test”);
}
}
class Main{
public static void main(String[] agrs){
Child child = new Child();
child.test();//Child test
}
}
这个例子好像能体现方法重写,但是他不是,它只是一个再普通不过的现象: Child对象调用Child类的静态方法。它只是体现了子类同名方法对父类方法的隐藏特性而已。
为什么这么肯定不是方法重写呢?我们直到方法重写会体现多态性。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
最后
今天的文章可谓是积蓄了我这几年来的应聘和面试经历总结出来的经验,干货满满呀!如果你能够一直坚持看到这儿,那么首先我还是十分佩服你的毅力的。不过光是看完而不去付出行动,或者直接进入你的收藏夹里吃灰,那么我写这篇文章就没多大意义了。所以看完之后,还是多多行动起来吧!
可以非常负责地说,如果你能够坚持把我上面列举的内容都一个不拉地看完并且全部消化为自己的知识的话,那么你就至少已经达到了中级开发工程师以上的水平,进入大厂技术这块是基本没有什么问题的了。
中…(img-vHOVvZv8-1713559239719)]
[外链图片转存中…(img-Pb2WIdAh-1713559239720)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
[外链图片转存中…(img-VyiQO6WR-1713559239720)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
[外链图片转存中…(img-cBjop1lr-1713559239720)]
最后
今天的文章可谓是积蓄了我这几年来的应聘和面试经历总结出来的经验,干货满满呀!如果你能够一直坚持看到这儿,那么首先我还是十分佩服你的毅力的。不过光是看完而不去付出行动,或者直接进入你的收藏夹里吃灰,那么我写这篇文章就没多大意义了。所以看完之后,还是多多行动起来吧!
可以非常负责地说,如果你能够坚持把我上面列举的内容都一个不拉地看完并且全部消化为自己的知识的话,那么你就至少已经达到了中级开发工程师以上的水平,进入大厂技术这块是基本没有什么问题的了。