文章目录
复习
多类合作
1. 自定义类型作为方法的参数
2. 自定义类型成为其他类型的成员变量/组成部分
静态
静态成员变量:
1. 静态成员变量推荐使用类名调用,不推荐使用类对象调用,因为静态成员变量和对象无关,【没有对象】
2. 静态成员变量在类文件加载过程中,定义在内存的【数据区】和对象所在的【堆区】无关,从内存角度分析,静态成员变量和类对象不属于同一个内存区域,两者无关【没有对象】
3. 静态成员变量在类文件加载阶段,已经具备数据存储能力和数据提供能力,是早于类对象出现,并且程序退出的过程中,首先销毁所有的实例化对象,JVM 才会销毁静态成员变量占用的数据空间,静态成员变量来的比对象早,走的比对象晚,生存周期要远超对象,两者无关【没有对象】
4. 静态成员变量是一个共享资源,并且针对于当前类而言独一份,所有使用的当前静态成员变量代码,使用的同是一个静态成员变量,静态成员变量无论通过哪一种手段进行数据的修改,从修改之后所有使用位置全部受到影响。
5. 静态成员变量常用于
a. 类内共享资源处理
b. 数据存储持久化需求选择
静态成员方法:
1. 静态成员方法要求使用类名调用,不推荐使用类对象调用,因为静态成员方法和类对象无关,【没有对象】
2. 静态成员方法中不可以直接使用类内的非静态成员变量,因为【没有对象】
3.静态成员方法中不可以直接使用类内的非静态成员方法,因为【没有对象】
4. 静态成员方法中可以直接调用类内的其他静态成员(静态成员变量和静态成员方法),【没有对象,难兄难弟】
5. 静态成员方法因为没有对象调用约束。可以节省创建对象时间和对象占用空间,执行效率较高
用于工具类封装
静态成员方法 ==> 类方法
静态成员变量 ==> 类变量
static, interface 和 生活案例
1. static
1.1 static 修饰静态代码块
1.11 代码块问题
什么是代码块
{} 只有大括号,里面的内容就是
1. 构造代码块
定义在类内
2. 局部代码块
定义在方法内
package com.qfedu.a_staticBLock;
// 构造代码块案例
public class Person {
private int id;
private String name;
private int age;
/*
* 这就是构造代码块
* 构造代码块,在成员变量之后,构造方法之前
*
* 通过代码运行内容可以看到的内容
* 1. 构造代码块在调用执行构造方法时一定执行
* 2. 构造代码块在调用执行构造方法时,首先执行
*
* 构造代码块内容会在在 Java 编译器编译过程中,直接给所有当前类的当前构造方法提供
* 并且在所有构造方法的【第一行 first statement】
*
* 可以将构造方法相同的功能模块,使用构造代码块封装/归纳/总结,并且可以提供
* 给所有的构造方法使用
*
*/
{
System.out.println("构造代码块执行");
}
public Person() {
System.out.println("构造犯法");
}
public Person(int id) {
this.id = id;
System.out.println("构造犯法");
}
public Person(int id, String name) {
this.id = id;
this.name = name;
System.out.println("构造犯法");
}
public Person(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
System.out.println("构造犯法");
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
package com.qfedu.a_staticBLock;
//局部代码块
public class Demo2 {
public static void main(String[] args) {
int num = 10;
// 局部代码块,可以优化变量内存占用时间,提升代码内存效率,降低内存
{
int num2 = 20;
}
System.out.println(num);
//System.out.println(num2);
}
}
1.12 static 修饰静态代码块基本语法和代码案例
// 静态代码块要求在 class 大括号以内
static {
}
package com.qfedu.a_staticBLock;
class SingleDog {
public int num = 10;
public static String test = "静态成员变量";
/*
* 静态代码块
* 在类文件加载阶段执行,有且只执行一次 ,因为 Java中的所有类型都是在
* 执行之前加载一次,不会重新加载
*
* static 修饰的静态代码块是否可以直接使用类内的非静态成员变量????
* 不能
*/
static {
/*
* Cannot make a static reference to the non-static field num
* 不能使用一个静态引用执行一个非静态成员变量 num
* static 修饰的静态代码块可以认为是一个静态区域,无法直接使用类内的非静态成员变量,因为【没有对象】
*/
//System.out.println(num);
/*
* static 修饰的静态代码块,可以直接使用类内的静态成员变量,因为【没有对象,难兄难弟,互不嫌弃】
*/
System.out.println(test);
/*
* Cannot make a static reference to the non-static method test() from the type SingleDog
* 不能使用一个静态引用执行/调用 SingleDog 类内非静态成员方法 test
*/
//test();
/*
* static 修饰的静态代码块,可以直接使用类内的静态成员方法,因为【没有对象,难兄难弟,互不嫌弃】
*
*/
testStaticMethod();
System.out.println("静态代码块内容");
}
public void test() {
System.out.println("非静态代码块内容");
}
public static void testStaticMethod() {
System.out.println("静态成员方法");
}
}
public class Demo3 {
public static void main(String[] args) {
System.out.println("测试");
SingleDog s1 = new SingleDog();
SingleDog s2 = new SingleDog();
SingleDog s3 = new SingleDog();
SingleDog s4 = new SingleDog();
SingleDog s5 = new SingleDog();
SingleDog s6 = new SingleDog();
SingleDog s7 = new SingleDog();
SingleDog s8 = new SingleDog();
SingleDog s9 = new SingleDog();
SingleDog s10 = new SingleDog();
}
}
1.13 静态代码块特征
1. static 修饰静态代码块,在程序加载阶段一定执行,有且只执行一次
2. static 修饰静态代码块,不能直接使用类内的非静态成员(成员变量和成员方法),因为【没有对象】
3. static 修饰静态代码块,可以直接使用类内的静态成员(类变量和类方法),因为【没有对象】
4. static 修饰静态代码块,用于项目启动过程中的初始化操作。
可以利用 static 代码加载阶段执行的特征,将一些项目执行所需的配置操作前置
用于 读取配置文件,加载相关驱动,加载第三方资源~~~~~
1.2 static 面试题
class Demo {
public static Demo d1 = new Demo();
public static Demo d2 = new Demo();
static {
System.out.println("静态代码块");
}
{
System.out.println("构造代码块");
}
public Demo() {
System.out.println("构造方法");
}
public static void main(String[] args) {
Demo d = new Demo();
}
}
/*
以上代码的执行流程:
构造代码块
构造方法
构造代码块
构造方法
// 以上是加载过程(出现打印是因为加在加载过程有sout)
静态代码块
构造代码块
构造方法
// 这才是执行过程
*/
/*
1. 代码需要执行,加载必要资源
2. Demo 类加载 ==> 所有的 static 修饰的静态内容准备就绪
static 修饰的静态内容平级按照最基本的顺序结构执行
3. 加载 static Demo d1
4. 加载 static Demo d2
5. 静态代码块加载执行
6. main 方法执行 Demo d 实例化
(实例化后 先调用构造方法代码块,再调用构造方法)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aCoeM3ag-1667577683485)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20221104115941692.png)]
2. interface 接口
2.1 生活中的接口
生活中的接口
USB 网线接口 RJ45 Type-C Lighting USB-C HDMI VGA Disply-Part minidp PCI-E SATA M-25ATA 3.5MM mircouUSB 电源(国际/英标/美标)
接口有什么用?
USB-B
连接鼠标,连接键盘,连接声卡,连接麦克风,连接耳机,充电,传输数据,U盘,移动硬盘。
USB
1. 指定的尺寸规范,并且不可以修改
宽度,高度,长度,引脚规范,电压,电流
2. 规范了连接标准,但是最终设备的功能由设备本身决定。
例如
鼠标连接 USB 控制光标
键盘连接 USB 输入设备
声卡连接 USB 声音控制
USB 是一个接口,是用来连接 USB 设备, 从而增强/拓展当前PC/电脑/笔记本
2.2 Java 中定义接口格式
当前阶段要求掌握接口的基本语法,格式规范,和使用要求
后期学习具体案例,特殊用法,架构设计
关键字:
interface
格式:
interface 接口名 {
成员变量
成员方法
}
1. 接口是一个特殊的类,也是一个数据类型
2. 接口名要求符合命名规则,见名知意,动宾结合,符合大驼峰命名规范。
3. 接口类型变量也是一个引用数据类型变量
/*
* 自定义接口 A
*/
interface A {
/*
* 成员变量
* The blank final field num may not have been initialized
* final 修饰的 num 可能尚未初始化
*
* final 从何而来? 斜体因为什么?
*
* 接口中成员变量的【缺省属性/默认属性】public static final
* public 表示数据公开,任何位置都可以使用 ==> USB 接口所有设备使用者 都可以知晓对应的尺寸信息
* static 静态修饰,独一份 ==> USB 相关数据独一份,大家都需要遵守
* final 最终修饰/不可以修改修饰,常量 ==> USB 接口数据不可以修改
*
* 【带有名称的常量】 ==> 下划线命名法处理,所有字母全部大写,不同英文单词下划线分割
*/
int NUM = 10;
/*
* Abstract methods do not specify a body
* abstract 修饰的方法没有方法体
*
* 接口中的成员方法【缺省属性/默认属性】 public abstract
* public 表示方法默认公开,标志公开 ==> USB 接口需要公开连接规则,连接方式,连接需求
* abstract 修饰没有方法体 ==> USB 接口仅指定方法要求,具体实现看对应设备,USB ==> 鼠标,键盘....
* USB 接口具体做什么,不是USB 接口本身决定,是由 USB 接口连接的设备决定。
*
*
* public abstract可写可不写,默认都不写
*/
void test();
}
2.3 遵从接口
类遵从接口
关键字:
implements
// 使生效, 工具
格式:
class 类名 implements 接口名 {
}
/**
* 一个非 abstract 修饰类【遵从】接口,要求实现接口所有缺省属性为
* public abstract 修饰的方法
*
* @author lenovo
*
*/
class TypeA implements A{
@Override
public void test() {
System.out.println("TypeA 类遵从接口A 实现test 方法");
}
}
public class Demo1 {
public static void main(String[] args) {
// 匿名对象直接调用
new TypeA().test();
TypeA typeA = new TypeA();
typeA.test();
}
}
2.4 接口的特殊用法
2.41 类可以遵从多个接口
package com.qfedu.b_interface;
interface B {
void testB();
// 和接口 C 方法声明一致的方法
void test();
}
interface C {
void testC();
// 和接口 B 方法声明一致的方法
void test();
}
/*
* 类不可以多继承,Java是单继承语言,也就是一个子类不可以有多个父类,一个父类可以有多个子类
* TypeB 类同时遵从两个接口,分别是interface B 和interface C
* 不同的接口直接使用 , + 空格隔开
*
* 语法要求:
* 1. 遵从多个接口的类,要求分别实现各个接口中的方法要求
* 2. 如果出现多个接口中存在完全相同的方法声明,实现类中有且只实现一个方法即可
*/
class TypeB implements B, C {
@Override
public void testC() {
System.out.println("TypeB 遵从接口C 实现testC 方法");
}
@Override
public void testB() {
System.out.println("TypeB 遵从接口B 实现testB 方法");
}
@Override
public void test() {
System.out.println("TypeB 遵从接口 B 和 接口 C 实现的两个接口中同规则方法");
}
}
public class Demo2 {
public static void main(String[] args) {
new TypeB().testB();
new TypeB().testC();
new TypeB().test();
TypeB typeB = new TypeB();
typeB.testB();
typeB.testC();
typeB.test();
}
}
2.42 类可以继承父类同时遵从接口
package com.qfedu.b_interface;
class SuperClass {
public void testA() {
System.out.println("父类成员方法");
}
}
interface D {
void testD();
}
/*
* TypeC 类继承 SuperClass 同时遵从接口 D
*/
class TypeC extends SuperClass implements D {
/*
* implements com.qfedu.b_interface.D.testD
* 紫色空心箭头 --> 实现接口中的方法
*/
@Override
public void testD() {
System.out.println("TYpeC 遵从接口 D 实现的 testD 方法");
}
/*
* overrides com.qfedu.b_interface.SuperClass.testA
* 绿色实习箭头 --> 重写父类继承到子类的方法
*/
@Override
public void tsetA() {
System.out.println("子类重写父类方法");
}
}
public class Demo3 {
public static void main(String[] args) {
TypeC typeC = new TypeC();
typeC.testA();
typeC.testD();
new TypeC().testA();
new TypeC().testD();
}
}
2.43 接口可以继承其他接口,并且可以多继承
package com.qfedu.b_interface;
interface USB1_0 {
void usb1_0Connect();
}
interface USB2_0 {
void usb2_0Connect();
}
/*
* 接口可以继承其他接口,同时允许多继承
*/
interface USB3_0 extends USB1_0, USB2_0{
void usb3_0Connect();
}
/*
* 类遵从接口,要求实现接口中所有的缺省属性/默认属性为 public abstract 修饰方法
* 包括当前接口的父接口要求方法
*
*/
class TypeD implements USB3_0{
@Override
public void usb1_0Connect() {
System.out.println("USB 1.0 协议规定方法");
}
@Override
public void usb2_0Connect() {
System.out.println("USB 2.0 协议规定方法");
}
@Override
public void usb3_0Connect() {
System.out.println("USB 3.0 协议规定方法");
}
}
public class Demo4 {
public static void main(String[] args) {
TypeD typeD = new TypeD();
typeD.usb1_0Connect();
typeD.usb2_0Connect();
typeD.usb3_0Connect();
new TypeD().usb1_0Connect();
new TypeD().usb2_0Connect();
new TypeD().usb3_0Connect();
}
}
2.44 JDK 1.8 版本以上特征
允许在接口中使用 default 关键字修饰方法,修饰的方法为默认方法,允许有方法体。
package com.qfedu.b_interface;
interface E {
void test();
default void testDefaultMethod() {
System.out.println("JDK 1.8 以上版本允许的默认方法 default 修饰");
}
}
class TypeE implements E {
@Override
public void test() {
System.out.println("TypeE 有且只需要完成即可 E 中的缺省属性为 public abstract 对应方法");
}
/*
* 重写接口中的 default 关键字修饰的方法
*/
/*
* @Override
* public void testDefaultMethod() {
* System.out.println("重写接口中的 default关键字修饰的默认成员方法");
* }
*/
}
public class Demo5 {
public static void main(String[] args) {
TypeE typeE = new TypeE();
typeE.test();
typeE.testDefaultMethod();
new TypeE().test();
new TypeE().testDefaultMethod();
}
}
2.45 接口语法细节
接口中是否可以使用 static 修饰的静态成员方法?
可以
static 修饰的方法直接通过该接口名直接调用
一个方法是否可以同时使用 abstract 和 static 关键字修饰?
不行
abstract 关键字修饰的方法没有方法体
static 修饰的方法是在类文件加载阶段已经准备就绪,已经具备执行能力,必须明确所有和执行相关的内容,权限修饰符,返回值类型,方法名,形式参数列表和方法体。
【static 修饰的方法必须有方法体】
【abstract 修饰的方法必须没有方法体】
两者无法合作!!!
4. 生活案例
3.1 动物园
动物 ==> 动物类
猴子 ==> 狮子类 ==> 动物类子类
老虎 ==> 老虎类 ==> 动物类子类
狮子 ==> 狮子类 ==> 动物类子类
饲养员需要去喂动物吃饭 ==> 方法
该方法所需参数类型:
动物类型
饲养员今天取为动物,不管是老虎,狮子还是猴子都算是动物
package com.qfedu.c_;
class Animal {}
class Monkey extends Animal {}
class Tiger extends Animal {}
class Lion extends Animal {}
public class Demo1 {
public static void mian(String[] args) {
Animal animal = new Monkey();
Monkey monkey = new Monkey();
Tiger tiger = new Tiger();
Lion lion = new Lion();
/*
饲养员今天去喂动物,不管是老虎,狮子还是猴子都算是动物
当前方法所需参数为 Animal 类型,这里可以直接传入的实际参数为 Animal 类对象
Monkey,Tiger,Lion 都是 Animal 动物类的子类,都是动物。
当前方法所需参数就是 动物类对象。可以提供给当前方法 Monkey
Tiger Lion 对应对象。
【Java 中语法规范】
一个方法所需参数为父类类型,传入的实际参数可以是父类对象或者其子类对象。
*/
feedAnimal(animal);
feedAnimal(monkey);
feedAnomal(tiger);
feedAnomal(lion);
}
/*
喂食方法,所需参数是动物类对象
用什么,拿什么,要什么,给什么
@param animal Animal 动物类对象
*/
public static void feedAnimal(Animal animal ) {
/*
getclass() 可以获取当前对象对应完整包名.类名
*/
System.out.println(animal.getClass() + "来吃饭了~~~");
}
}
3.2 USB接口
4. 作业
1. 整理笔记
2. 案例代码三遍
3. 冷静思考对象知识点
4. 案例代码三遍
可以直接传入的实际参数为 Animal 类对象
Monkey,Tiger,Lion 都是 Animal 动物类的子类,都是动物。
当前方法所需参数就是 动物类对象。可以提供给当前方法 Monkey
Tiger Lion 对应对象。
【Java 中语法规范】
一个方法所需参数为父类类型,传入的实际参数可以是父类对象或者其子类对象。
/
feedAnimal(animal);
feedAnimal(monkey);
feedAnomal(tiger);
feedAnomal(lion);
}
/
喂食方法,所需参数是动物类对象
用什么,拿什么,要什么,给什么
@param animal Animal 动物类对象
*/
public static void feedAnimal(Animal animal ) {
/*
getclass() 可以获取当前对象对应完整包名.类名
*/
System.out.println(animal.getClass() + "来吃饭了~~~");
}
}
##### 3.2 USB接口
#### 4. 作业
- 整理笔记
- 案例代码三遍
- 冷静思考对象知识点
- 案例代码三遍