面向对象高级01
面向对象高级
一、类变量和类方法
1.1类变量和类方法
1.1.1 static变量是对象共享的,不管static变量在哪里
1.1.2 共识:
(1)static 变量是同一个类的对象共享。(2)static变量在类加载的时候就已经生成了
1.1.3 什么是类变量?
类变量也叫静态变量,是该类的所有对象共享的变量,任何一个该类的对象去访问他时取到的都是相同值,同样任何一个该类的对象去修改他时,修改的也是同一个变量。
1.1.4 定义语法:
访问修饰符 static 数据类型 变量名;
1.1.5 细节
静态方法是能只能访问静态成员
普通成员方法既可以访问 非静态方法, 也可以访问静态的成员
1.1.6小结
记住两句话
(1) 静态方法智能访问静态成员
(2) 非静态方法可以访问所有成员
(3) 在写代码的时候,仍然要遵循访问权限规则
二、理解main方法
2.1.1深入理解main方法
解释main方法的形式
public static void main(String[] args){}
- main方法是虚拟机在调用
- java虚拟机需要调用类的main方法,所以该方法的访问权限必须是public
- java虚拟机在执行main() 方法的时候不必创建对象,所以该方法必须是static
- 该方法接受String类型的参数, 该数组中保存执行java命令时所传递给运行类的参数
- java 执行的程序 参数1 参数2 参数3.........
2.1.2特别提示
- 在main方法中,我们可以直接调用main方法所在类的静态方法或静态属性
- 但是 不能直接访问该类中的非静态成员, 必须创建该类的一个实例后,才能通过这个对象去访问类中的非静态成员
2.1.3 代码块使用细节
- static代码块也叫静态代码块,所用是对类进行初始化,而他随着类的加载而执行并且只会执行一次。如果是普通代码块,每创建一个对象就执行。
- *** 背*** 类是什么时候被加载 创建对象实例时 创建子类对象实例,父类也会被加载 使用静态成员的时候
- 普通代码块,在创建对象实例时,会被隐藏式的调用。被创建一次就会调用一次。如果只是使用静态成员的时,普通代码块并不会执行
小结:
静态代码块是类加载的时,执行,只会执行一次
普通代码块是在创建对象的时候用的,创建一次执行一次
- 创建一个对象的时候,在一个类的调用顺序
先调用静态代码块和静态属性初始化 先后顺序和定义顺序相同
然后调用普通代码块和普通属性初始化,先后顺序和定义顺序相同
最后调用构造方法
上述一定要记住,最好理解的记
- 静态代码块只能调用静态成员,普通代码块可以调用任意成员
三、单例设计模式
单例(单个实例)
所谓单例设计模式,就是采取一定的方法保证在整个的软件系统中对某个类只存在一个对象实例,并且该类只提供一个去的该类对象实例的方法
3.1.1 饿汉式[在类加载的时候就已经创建好对象了]
- 构造器私有化 => 防止直接new
- 类的内部创建对象
- 向外部暴露一个静态的公共方法。getInstance
- 代码实现
package com.wxledu.single_; public class SingleTon01 { public static void main(String[] args) { //通过方法可以获取 GirlFriend instance = GirlFriend.getInstance(); System.out.println(instance.getName()); } } //有一个类 GirlFriend //只能有一个女朋友 class GirlFriend{ private String name; //如何保证我们只创建一个对象 //步骤 //1. 将构造器私有化 private GirlFriend(String name) { this.name = name; } //2. 在类的内部创建爱你对象 //为了能够在静态方法中, 返回 gf 对象,要将其修饰为 static private static GirlFriend gf = new GirlFriend("小红"); //3. 提供一个公共的static方法, 可以返回 gf 对象 public static GirlFriend getInstance(){ return gf; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
3.1.2 懒汉式
饿汉式可能造成,创建了对象但是没有使用
package com.wxledu.single_; /** * 演示懒汉式的 单例模式 */ public class SingleTon02 { public static void main(String[] args) { System.out.println(Cat.n1); Cat instance = Cat.getInstance(); System.out.println(instance); //再次调用 getInstance() Cat instance1 = Cat.getInstance(); System.out.println(instance1); System.out.println(instance == instance1); } } //希望在程序运行过程中只能创建一个 Cat 对象 //使用单例模式 class Cat{ private String name; public static int n1 = 888; private static Cat cat; //步骤 //1. 仍然构造器私有化 //2. 定义一个 static 属性对象 //3. 提供一个 public 的 static 方法,可以返回一个 cat 对象 //4. 只有当用户使用方法 getInstance() 的时候才返回 cat 对象,从而保证了单一 public Cat(String name) { System.out.println("构造器被调用...."); this.name = name; } public static Cat getInstance(){ if (cat == null){//如果还没创建对象 cat = new Cat("小可爱"); } return cat; } @Override public String toString() { return "Cat{" + "name='" + name + '\'' + '}'; } }
3.1.3 两者比较
- 两者的主要区别就是创建的时机不同, 饿汉式实在类加载的时候就创建了实例对象,懒汉式是在用的时候才创建
- 饿汉式不存在线程安全问题,懒汉式存在线程安全问题
- 饿汉式存在加载资源浪费的可能,因为如果一个对象实例都没有使用,那么饿汉式创建的对象就浪费了,懒汉式是使用时才创建,就不存在这个问题了
四、final 关键字
final 中文意思: 最后的,最终的
final 可以修饰类,属性,方法和局部变量
在一下几种情况,程序员可能有如下需求,就会用到 final :
- 当不希望类被继承时,可以用final
- 当不希望父类的某个方法被子类覆盖/重写(override)时,可以用final关键字修饰
- 当不希望类的某个属性的值被修改的时候,可以用final修饰
- 当不希望某个局部变量被修改,可以使用final修饰
4.1.1 使用细节
- final修饰的属性又叫常量, 一般用 XX_XX_XX来命名
- final修饰的属性在定义时,必须赋初值,并且以后不能在修改,赋值可以加在一下位置之一
定义时: 如 public final double TAX_RATE = 0.8;
在构造器中
在代码块中
- 如果final修饰的属性是静态的,则初始化的只能是
定义时
在静态代码块 不能在构造器中赋值
- final 类不能被继承, 但可以实例化对象
- 如果类不是final类, 但含有final方法,则该方法不能被重写,但可以被继承
- 一般来说如果一个类已经是包装类,就没必要在将他的方法修饰成final方法
- final不能修饰构造方法即构造器
- final和static往往搭配使用,效率更高,不会导致类的加载,底层编译做了优化处理
- 包装类 ( Integer Double Float Boolean 等都是 final ) String 也是final
五、抽象类
当父类的某些方法,需要声明,但又不确定如何实现时,可以将其声明为抽象方法,那么这个类就是抽象类
抽象方法没有方法体
抽象类的价值更多在于设计,是设计者设计好后,让子类继承并实现抽象类
5.1.1 抽象类的细节
- 抽象类不能被实例化
- 抽象类不一定包含 abstract 方法 也就是说,抽象类可以没有 abstract 方法
- 一旦包含了 abstract 方法, 则这个类必须声明为 abstract
- abstract 只能修饰类和方法 , 不能修饰属性和其他的
- 抽象类可以有任意成员(因为抽象类还是类), 比如:非抽象方法,构造器,静态属性等
- 抽象方法不能有主题
public abstract void eat();
- 如果类继承了抽象类,则必须实现抽象类的所有抽象方法,除非他自己声明为 abstract 类
- 抽象方法不能使用 private final 和 static 来修饰,因为这些关键词都和重写想违背的
六、接口
6.1.1 接口使用细节
- 接口不能被实例化
- 接口中所有的方法是 public 方法 , 接口中的抽象方法可以不用 abstract 修饰,一个普通类实现的方法就必须将该方法的所有抽象类实现
- 抽象类实现接口,可以不用实现接口的方法
- 一个类可以实现多个接口
- 接口中的属性只能是 final 而且是 public static final 修饰。比如:int a = 1; 实际上是 public static final int a = 1; (必须初始化)
- 接口中属性的访问形式:接口名, 属性名
- 一个接口不能继承其他类,但可以继承多个别的接口
interface A extends B,C {}
- 接口的修饰符,只能是 public 和默认, 这点和类的修饰符是一样的
6.1.2 接口 VS 继承类
- 接口和继承解决的问题不同
- 继承的价值主要在于:解决代码的复用性和可维护性
- 接口的价值主要在于:设计,设计好各种规范,让其他类去实现这些方法,即更加灵活
- 接口比继承更加灵活
接口相比继承更加灵活,继承是满足 is - a 的关系,而接口只需要满足 like - a 的关系
- 接口在一定程度上实现代码解耦
package com.wxledu.interface_; public class Computer { //编写一个方法, 计算机开始工作 //解读: //1. UsbInterface usbInterface 形参是接口类型 UsbInterface //2. 看到 接收 实现了 UsbInterface 接口的类的对象实例 public void work(UsbInterface usbInterface){ //规定接口的相关方法,老师规定的,及规范..... //通过接口调用方法 usbInterface.start(); usbInterface.stop(); } }
- 接口和继承的多态
- 接口可以指向实现了接口的对象实例
- 继承父类可以指向实现了父类的子类实例
6.1.3 演示接口多态的传递
package com.wxledu.interface_; /** * 演示接口的多态传递 */ public class InterfacePolyPass { public static void main(String[] args) { //接口类型的变量可以指向,实现了该接口的类的对象实例 IG ig = new Teacher(); // 如果 IG 继承了 IH 接口, 而Teacher 实现了 IG 接口 // 那么实际上就相当于 Teacher 这个类实现了 IH 接口 // 这就是所谓的接口多态的传递现象 IH ih = new Teacher(); } } interface IH{} interface IG extends IH{} class Teacher implements IG{ }
本文作者:TomLove
本文链接:https://www.cnblogs.com/tomlove/p/17642944.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人