文章目录
面向对象进阶
一、static
- 静态,可以修饰成员变量、成员方法
- 不能修饰局部变量
1.static修饰成员变量
- 成员变量按照有无static修饰,分为两种:
类变量(静态变量):有static修饰,属于类,在计算机里面只有一份,会被类的全部对象共享
访问: 类名.类变量(推荐) 对象.类变量(不推荐)
实例变量(对象的变量):无static修饰,无static修饰,属于每个对象的
- 特点
- 被该类所有的对象所共享
- 随着类的加载而进入内存
- 应用场景
在开发中,如果某个数据只需要一份,且希望能够被共享,则该数据可以定义成类变量来记住
2.static修饰成员方法
- 分类
类方法(静态方法):有static修饰的成员方法,属于类
访问: 类名.类方法【推荐】 CodeUtil.getCode() 对象.类方法【不推荐】
实例方法:无static修饰的成员方法,属于每个对象
- 特点
- 静态方法可以直接使用静态变量
- 非静态方法【实例方法】可以直接使用静态成员、非静态成员
- 应用场景【作为工具类 class XxxUtil】
- 做为工具类【clss XxxUtil】
工具类中的方法都是一些类方法,每个方法都是用来完成一个功能的,是给开发人员共同使用的
- 好处:提高了代码的复用性,调用方便,提高开发效率
Tips:
为什么工具类中的方法都要用类方法,而不是用 实例方法
实例方法需要创建对象来调用,此时对象只是为了调用方法,对象占内存,这样会浪费内存;
类方法:直接用类名调用即可,调用方便,也能节省内存。
工具类没有创建对象的需求,建议将工具类的构造器私有
3.使用类方法、实例方法时的注意事项
- 类方法中可以直接访问类的成员,不可以直接访问实例成员[new对象之后使用]
- 实例方法中既可以直接访问类成员,也可以直接访问实例成员
- 实例方法中可以出现this关键字,类方法中不哭出现this关键字的
- 先到不能访问后到,后到可以访问先到【到内存】
4.static应用知识:代码块
- 是类的5大成分之一(成员变量、构造器、方法、代码块、内部类)
- 分类
- 静态代码块
格式:static { }
特点:类加载时自动执行,由于类只会加载一次,所以静态代码块也会执行一次
作用:完成类的初始化,例如:对类变量的初始化赋值
- 实例代码块[构造代码块]
格式:{ }
特点:每次创建对象时,执行实例代码块,并在构造器前执行
作用:和构造器一样,都是用来完成对象的初始化的,例如:对实例变量进行初始化赋值
二、static应用:单例设计模式
1.设计模式
-
一个问题通常有n种解法,其中肯定有一种解法是最优的,这个最优的解法被人总结出来了,称之为设计模式[具体问题的最优方案]。
-
设计模式有 23 种,对应20多种软件开发中会遇到的问题
2. 饿汉式单例设计模式
确保一个类只有一个对象
- 写法
- 把类的构造器私有 —— [为了不让外界访问到并创建对象]
- 定义一个类变量记住类的一个对象
- 定义一个类方法(静态方法),返回对象【返回值类型:房钱类名】
public class Sinfleton{ private Singlton(){ } private static Singleton instance = new Singleton(); public static Singleton getInstance(){ return instance; } }
- 应用场景和好处
- 场景:任务管理器对象,获取运行时对象。
- 好处:在这些业务场景下,使用单例模式,可以避免浪费内存~
- 案例
//singlten 对象类
package d1_static.singleton;
/*
单例设计模式:让类只能有一个对象
*/
public class Singleton {
//1.私有构造方法
private Singleton(){
}
//2.外界无法创建对象,此处提供一个对象工外界访问
public static Singleton instance = new Singleton();
//3.提供一个方法,让外界访问 instance
public static Singleton getInstance(){
return instance;
}
}
//main
package d1_static.singleton;
public class Demo {
public static void main(String[] args) {
Singleton s1 = Singleton.instance;
Singleton s2 = Singleton.instance;
System.out.println(s1 == s2);// true
// Singleton.instance = null;
//置为 null 就没有对象了 - 在对象类中提供一个方法访问
//对象类中提供 getInstance() 方法访问
Singleton s3 = Singleton.getInstance();
System.out.println(s3 == s1);// true
}
}
3. 懒汉式单例设计模式
拿对象时,才开始创建对象
- 写法
- 把类的构造器私有
- 定义一个类变量用于存储对象
- 定义一个类方法,保证返回的是同一个对象
public class Singleton{ private Singleton(){ } private static Singleton instance; public static Singleton getInstance(){ if (instance == null){ instance = new Singleton(); } return instance; } }
- 特点
- 要用类的对象时才创建对象(延迟加载对象)
- 案例
/*
* 懒汉式单例设计模式:
*/
public class Singleton {
//1.私有构造方法
private Singleton() {
}
//2.定义一个类变量用于存储对象
private static Singleton instance;
//3.定义一个类方法,保证返回的是同一个对象
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
// main
public class Demo {
public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s1 == s2);// true
}
}
三、继承
1.继承概述
- Java中提供了一个关键字extends,用这个关键字,可以让一个类和另一个类建立起父子关系
- 继承特点
- 子类能继承父类的非私有成员(成员变量、成员方法)
- 继承后对象的创建:子类的对象时由子类、父类共同完成的【调用子类时,先加载其父类】
好处:减少重复代码的编写,提高代码【复用性】
2.继承相关注意事项
2.1 权限修饰符
- 用来限制类中的成员(成员变量、成员方法、构造器、代码块…)能够被访问的范围
种类及其范围:
- private:只能本类
- 缺省:本类、同一个包中的类
- protected:本类,同一个包中的类、子孙类中,其他包下的子类也可以访问
- public:任意位置
private < 缺省 < protected < public
修饰类 | 本类里 | 同一个包中的类 | 子孙类 | 任意类 |
---|---|---|---|---|
private | √ | |||
缺省 | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
2.2 单继承、Object
- 单继承
Java是单继承的:一个类只能继承一个直接父类;Java中的类不支持多继承,但是支持多层继承
- Object
object类是java所有类的祖宗类(超类)。我们写的任何一个类,其实都是object的子类或子孙类
2.3 方法重写
-
当子类觉得父类中的某个方法不好用,或者无法满足自己的需求时,子类可以重写一个方法名称、参数列表一样的方法,去覆盖父类的这个方法,这就是方法重写。
子类写了一个方法名称,形参列表与父类某个方法一样的方法去覆盖父类的该方法
注意:重写后,方法的访问,Java会遵循就近原则
注意点:
- 重写小技巧:使用Override注解,他可以指定java编译器,检查我们方法重写的格式是否正确,代码可读性也会更好。
- 子类重写父类方法时,访问权限必须大于或者等于父类该方法的权限( public > protected > 缺省 )。
- 重写的方法返回值类型,必须与被重写方法的返回值类型一样,或者范围更小。
- 私有方法、静态方法不能被重写,如果重写会报错的。
面试题:
1.方法重载和方法重写的区别?
方法重载overload:在一个类中,同名的方法有不同的参数列表(参数类型、个数、顺序 不同)视为重载。比如:实体类中的无参构造器和有参构造器。
方法重写override:子类把父类背身有的方法重新写一遍。
2.new String(); 和 直接赋值String s = "",区别?
new String():创建一个String类型的对象,可能会创建1~2个对象,先创建1个对象,之后在赋值的时候先在字符串常量池中查找有没有对应的字符串,如果有,直接引用,没有则再创建一个对象。
String s = "":直接赋值,可能会创建一个或不创建对象,先在 字符串常量池中查找有没有对应的字符,如果有,直接引用,没有则创建1个对象。
- 应用场景:当子类觉得父类的方法不好用,或者不满足自己的需求时,就可以用方法重写
2.4 子类中访问其他成员的特点
- 在子类方法中访问其他成员(成员变量、方法),是依照就近原则的
- 先子类局部范围找
- 然后子类成员范围找
- 然后父类成员范围找,如果父类范围还没有找到则 报错
- 子类调用父类方法[super.方法名]
- 可以通过super关键字,指定访问父类的成员:super.父类成员变量/父类成员方法
2.5 子类构造器
- 特点
- 子类的全部构造器,都会先调用父类的构造器,再执行自己
- 子类构造器是如何实现调用父类构造器的:
默认情况下,子类全部构造器的第一行代码都是 super() (写不写都有) ,它会调用父类的无参数构造器。
如果父类没有无参数构造器,则我们必须在子类构造器的第一行手写super(….),指定去调用父类的有参数构造器。
2.6 补充知识
- this(…)调用兄弟构造器
-
任意类的构造器中,是可以通过this(…) 去调用该类的其他构造器的
-
注意事项:
this(…) 、super(…) 都只能放在构造器的第一行,因此,有了this(…)就不能写super(…)了,反之亦然
- super(…)调用父类有参数构造器的常见应用场景
为对象中包含父类这部分的成员变量进行赋值
- this和super详情
- this:代表本类对象的引用
- super:代表父类存储空间的标识
关键字 | 访问成员变量 | 访问成员方法 | 访问构造方法 |
---|---|---|---|
this | this.成员变量 访问本类成员变量 | this.成员方法(…) 访问本类成员方法 | this(…) 访问本类构造器 |
super | super.成员变量 访问父类成员变量 | super.成员方法(…) 访问父类成员方法 | super(…) 访问父类构造器 |