java基础-day11-static关键字
2021-06-26 本文已影响0人
触手不可及
static关键字和接口
1. static关键字【重点】
1.1 static修饰静态成员变量
1.1.1 为什么要使用静态成员变量
开发中存在一些共享数据,这些数据存在于每一个类对象中,并且一致数据!!!如果每一个对象都存储当前数据,会导致大量的资源浪费!!!
共享单车
共享资源,共享经济
1. 共享单车不占用用户空间。占用公共空间。
2. 共享单车是否与你有关???
所属权归共享单车的运营公司
每一个用户拥有使用权。
3. 共享单车被XXX卸了座,大家都无法使用。
4. 你来到北京之前,共享单车已经存在,你走之后,共享单车依然存在。
饮水机
共享资源
1. 占用共享空间,不占用用户空间
2. 饮水机与你有关?
只能使用
3. 饮水机在这里,你走之后,它还在这里。
1.1.2 静态成员变量从生活角度总结
1. 静态成员变量占用的内存空间是一个【公共空间/共享空间】
2. 静态成员变量所属权非对象所有。
3. 静态成员变量一旦被修改,或者出现问题,所有使用者都会受到影响
4. 静态成员变量生存周期是比对象要长久一点点,来的比对象早,走的比对象晚
1.1.3 static修饰静态成员变量代码演示
package com.qfedu.a_staticfield;
// Ctrl + D 删除当前行
class Person {
public String name;
public int age;
// 国籍是存在共享数据性质,这里可以使用static修饰
public static String country = "中华人民共和国";
public Person() {}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Demo1 {
public static void main(String[] args) {
Person p1 = new Person("杨洋", 16);
Person p2 = new Person("达康", 66);
Person p3 = new Person("昊昊", 6);
Person p4 = new Person("帅栋", 30);
/*
* 通过类名方式直接调用静态成员变量,就是所谓的静态方式,没有任何的警告
* 这里IDE工具也是在提示你,static修饰的内容和【对象】无关,【没有对象】
*/
System.out.println(Person.country);
/*
* The static field Person.country should be accessed in a static way
* Person类内static修饰的静态变量 country应该通过静态方式访问
*/
System.out.println(p1.country);
System.out.println(p2.country);
System.out.println(p3.country);
System.out.println(p4.country);
/*
* 静态成员变量不管通过哪一种方式修改,所有使用位置都会受到影响
* 这里其实也是【共享数据】的一个基本规范。
*/
Person.country = "PRC";
// p1.country = "PRC";
System.out.println(p1.country);
System.out.println(p2.country);
System.out.println(p3.country);
System.out.println(p4.country);
}
}
package com.qfedu.a_staticfield;
public class Demo2 {
public static void main(String[] args) {
/*
* 在没有Person类对象情况下,依然调用了country静态成员变量
*/
System.out.println(Person.country);
// 创建了一个Person对象,但是是一个匿名对象,【阅后即焚】
new Person();
/*
* Person对象被销毁之后,静态成员变量依然可以使用,
*/
System.out.println(Person.country);
}
}
1.1.4 静态成员变量分析
![](https://img.haomeiwen.com/i25121334/4ebcac47db61f868.png)
静态成员变量所属权非对象所有,和对象无关???
1. 内存占用角度
静态成员变量占用的内存空间是内存【数据区】
类对象占用的内存空间是一个内存【堆区】
两者不再同一个内存空间中,有且只是类对象中存在一个【引用数据类型变量】指
向数据区静态成员变量。
2. 代码中没有类对象依然可以使用静态成员变量
在没有类对象情况下,可以通过类名直接调用对应的静态成员变量
在对象被销毁之后,依然可以通过该类名调用静态成员变量
与对象无关,【没有对象】
静态成员变量一旦被修改,或者出现问题,之后所有使用者都会受到影响
这是共享资源的基本特征。
静态成员变量是在内存的数据区,所有的使用操作都是唯一的静态成员变量,不管是通过类名修改操作,还是通过类对象修改操作,修改使用的内存都是同一个内存。
静态成员变量生存周期是比对象要长久一点点,来的比对象早,走的比对象晚【重点】
static修饰的静态成员变量是在【类文件加载阶段完成定义和内存划分】
类文件:
Demo1.java ==> javac.exe ==> Demo1.class
二进制文件/字节码文件/类文件
加载阶段:
程序运行之前的loading阶段(读条),准备好所有运行之前准备工作
静态成员变量在程序之前的准备阶段已经完成定义和内存划分。当前情况下静态成员变量已经可以使用。当前情况下是没有创建对象的。【没有对象】
Java程序退出之前,首先会将所有的占用内存全部归还给计算机。这里涉及到JVM的GC机制,会销毁所有的类对象,任何在释放【类文件占用内存空间】。释放类文件空间的过程中,会销毁【静态成员变量占用数据区内存空间】。销毁时间要晚于类对象。【】
1.2 static修饰静态成员方法
1.2.1 静态成员方法代码演示
package com.qfedu.b_staticmethod;
class SingleDog {
// 非静态成员变量
private String name;
private int age;
// 静态成员变量
private static String country = "中华人民共和国";
// 非静态成员方法
public void whyYouSingleDog() {
name = "彭于晏";
System.out.println("别太拼...");
}
// 静态成员方法
public static void testStatic() {
/*
* Cannot make a static reference to the non-static field name
* 静态成员方法中,不得使用类内的非静态成员变量
*/
/*
* Cannot make a static reference to the non-static method whyYouSingleDog() from the type SingleDog
* 静态成员方法中,不得使用类内的非静态成员方法
*/
// whyYouSingleDog();
/*
* Cannot use this in a static context
* 不能在一个静态区域能使用this关键字
*/
// System.out.println(this);
/*
* 静态成员方法可以使用类内的静态成员变量和类内的静态成员方法 【难兄难弟】
*/
System.out.println(country);
test();
System.out.println("静态成员方法");
}
public static void test() {
System.out.println("其他静态成员方法");
}
}
public class Demo1 {
public static void main(String[] args) {
/*
* The static method testStatic() from the type SingleDog should be accessed in a static way
* SingleDog类内的静态成员方法testStatic()应该通过静态的方法操作访问
*/
new SingleDog().testStatic();
/*
* 推荐使用类名直接调用类内的静态成员方法。
*/
SingleDog.testStatic();
}
}
1.2.2 静态成员方法使用注意事项
1. 静态成员方法推荐使用类名直接调用,不推荐使用类对象调用。因为【没有对象】
2. 静态成员方法不能使用类内的非静态成员(非静态成员 ==> 成员变量和成员方法),因为【没有对象】
3. 静态成员方法可以使用类内的其他静态成员(静态成员 ==> 静态成员变量和静态成员方法),【难兄难弟】
4. 静态成员方法在类文件加载阶段已经定义完成,早于类对象出现,晚于类对象销毁。所以【没有对象】
1.2.3 静态成员方法注意事项解释
静态成员方法在类文件加载阶段已经定义完成
静态成员方法随着类文件的加载而加载完成。
静态成员方法的加载完成标准
1. 明确所有的内容 返回值类型,方法名和形式参数列表。三要素准备就绪
2. 方法体内功能代码完备,可以执行。
3. 加载完毕之后,当前方法已经具备执行能力。
静态方法是推荐使用类名调用的!!!
调用当前方法的方式非对象方式,所有和对象相关的内容,都无法使用。
静态成员方法是在类文件加载阶段准备就绪,此时是没有任何的对象存在的!!!
1.2.4 静态成员方法使用
Arrays.toString();
静态成员方法优势:
1. 通过类名调用,简单直接
2. 没有类对象约束,同时也没有无关的内存浪费。
3. 静态成员方法所需参数全部是外来数据
一般情况下静态成员方法通常作为工具类使用。
Arrays工具类
数组操作的工具类
BeanUtils工具类
操作符合JavaBeans规范的类对象工具类
package com.qfedu.b_staticmethod;
import java.util.Arrays;
public class Demo2 {
public static void main(String[] args) {
int[] arr = {2, 3, 5, 7, 2, 2, 4, 2, 8, 10};
/*
* Arrays工具类
* static String toString(任意类型数组);
* 返回数据是当前数组的字符串描述形式
* [元素, 元素, 元素]
*/
String str = Arrays.toString(arr);
System.out.println(str);
/*
* Arrays工具类
* static void sort(基本数据类型数组);
* 快速排序,默认方式为升序,效率高的吓人,但是内存浪费也吓人
* 时间换空间,空间换时间
*/
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
/*
* Arrays工具类
* static int binarySearch(任意类型数组, 指定查询数据);
* 找出指定数据在数组中的下标位置,二分法查找。
* 二分法查询要求当前数据必须是通过sort排序的,如果未排序,不保证数据
* 查询结果有效性。
* 二分法查找 不保证找的数据是第几个
*/
int index = Arrays.binarySearch(arr, 0);
System.out.println(index);
}
}
1.3 static修饰静态代码块
1.3.1 代码块都有什么?
构造代码块
在class大括号以内
只要调用当前类内的构造方法,就一定执行构造代码块内容,并且是先于构造方法
执行
{}
局部代码块
在方法大括号以内
在方法中为了极致的约束变量的操作范围,提高内存的回收效率,使用的代码块
{}
静态代码块
在class大括号以内
只要当前类文件加载,就一定会执行static代码块以内的内容
【注意】
代码块中类文件的加载是当前程序中的确需要当前类提供一定的数据支持,才
会被JVM执行加载
static {
}
1.3.2 静态代码块使用特征
1. 静态代码块不能使用类内的非静态成员【没有对象】
2. 静态代码块不能使用this关键字 【没有对象】
3. 静态代码块能使用类内的静态成员
4. 静态代码块在类文件加载阶段执行完毕,并且有且只执行一次。
作用:
主要用于程序初始化过程。
JDBC
所使用驱动 Driver 对应数据库的 URL 数据库登陆所需 User 和 Password
1.4 静态面试题
// 【重点】
class Demo {
static Demo d1 = new Demo();
static Demo d2 = new Demo();
{
System.out.println("构造代码块");
}
static {
System.out.println("静态代码块");
}
public Demo() {
System.out.println("构造方法");
}
public static void main(String[] args) {
Demo d = new Demo();
}
}
/*
分析代码的执行流程
构造代码块
构造方法
构造代码块
构造方法
静态代码块
构造代码块
构造方法
*/
![](https://img.haomeiwen.com/i25121334/f8903d9ab0d48ad2.png)
// 不要忘记知识点本来的样子
class Demo {
Demo d1 = new Demo();
static Demo d2 = new Demo();
{
System.out.println("构造代码块");
}
static {
System.out.println("静态代码块");
}
public Demo() {
System.out.println("构造方法");
}
public static void main(String[] args) {
Demo d = new Demo();
}
}
/*
分析代码的执行流程
代码运行错误
会导致StackOverFlowError 内存溢出
因为类对象创建过程中会执行成员变量初始化操作,而在代码中存在一个成员变量
也在创建当前类对象,这里会导致构造方法无限递归。
*/
1.5 静态总结
1. 静态修饰的内容都是在类文件加载阶段进行操作的
静态成员变量和静态成员方法是准备就绪,随时都可以通过类名直接调用。
静态代码块直接执行,而且有且只执行一次,按照最基本的【顺序结构】执行。
2. 所有静态修饰的内容,都无法直接使用与对象相关内容,
3. 静态成员变量存在共享性和持久性。
静态成员方法工具方法,没有对象约束更加方法
静态代码块用于初始化整个程序,JDBC会涉及到
4. 静态之间的内容可以相互使用,相互操作。
2. 接口
2.1 生活中的接口
生活中常用接口:
USB-A, USB-B, USB-C, PCI-E, RJ45, 3.5MM, HDMI, DisplayPort. SATA
M.2 SATA
接口能做什么???
USB
充电,键盘,鼠标,U盘,硬盘,麦克风,转网线,声卡...
接口只指定规范,接口连接的设备,决定当前操作的功能。
2.2 Java中定义接口的格式和规范
关键字:
interface UI ==> User Interface
定义接口的格式:
interface 接口名 {
成员变量;
成员方法;
}
接口规定数据,不能改变
接口指定的规范,由别人实现
interface A {
// 成员变量
// The blank final field num may not have been initialized
// 接口中成员变量缺省属性/默认属性 public static final
int num = 10;
// 成员方法
// Abstract methods do not specify a body
// 接口中成员方法缺省属性/默认属性 public abstract
void test();
}
.2..3 Java中遵从接口的使用基本规范
关键字
implements
格式:
class TypeA implements A {
要求当前遵从接口A的实现类,必须完成接口中所有的缺省属性为abstract的方法。
}