week02_day03
static关键字
1.static引例:
2.static修饰的成员变量存储在方法区
························································································································································································
下面全是干货:
一、首先区分几个概念:
静态成员变量-----静态变量
静态成员方法-----静态方法
普通成员变量-----成员变量
普通成员方法-----成员方法
static关键字:可以修饰普通成员变量和普通成员方法
说明一下: 按照严格意义上的面向对象思想, static修饰成员变量,和static修饰成员方法,都不能算做类中定义的成员。 我们之所以称static修饰的变量为 静态成员变量(习惯上的称呼),方法为 静态成员方法(习惯上的称呼),是因为它写在类体中的。
二、为什么引入static关键字?
例如Student类中有一个String schoolName的成员变量,而我们统计的是吉林大学的学生,所以schoolName的值应当统一为"吉林大学",这时,可以static String schoolName,将schoolName设置为静态变量,所有Student对象共享这一变量,都可以对这一变量进行访问和修改。
三、static关键字的特点:
-
被类的所有 对象所共享:(判定是否使用static的关键)
a. 当static修饰了成员变量,该成员变量的值,就不在存储与对象中了,而是单独存储了一份,被类的所有对象所共享。
b. 当static修饰成员方法的时候,该方法被当前类的所有对象共享当前类对象.方法(和普通成员方法从共享的角度,几乎没有太大区别) -
可以通过类名访问
a. 可以通过类名直接访问,static成员变量的值
如:Student.SchoolName
b. 直接通过类名直接调用,static成员方法
如:Student.getSchoolName(); -
随着类的加载而加载
a. static成员变量,随着类加载过程,其实就已经在方法区中,分配了内存
b. static成员方法, 一旦类加载完毕,我们就可以直接访问,static方法,而不必创建对象,然后在对象名. 访问方法 -
优先于对象而存在,不依赖于对象而存在
a. 成员变量的角度来理解,static修饰的成员变量,不在依赖于对象而存在,因为static修饰的成员变量的值,不在存储在,该类的每个对象中。作为对比,没有被static修饰的成员变量,都依赖于对象而存在,因为他们的值,都存储在对象中
b. 成员方法角度,被static修饰的成员方法,在没有对象存在的情况下,也可以直接通过类名来调用方法,作为对比,没有被static修饰的,普通成员方法,它依赖于对象而存在, 原因是,普通成员方法中,可以访问,普通成员变量的值,而普通对象的值又是依赖于对象而存在的 -
先出现在内存
静态成员变量, 一定先于没有被static修饰的普通成员变量,出现在内存中。因为静态成员变量随着类的创建而创建,随着类的销毁而销毁,而普通成员变量随着对象的创建而创建,随着对象的销毁而销毁,而一定是先有类后才有对象的。
注意事项:如果我们在非静态成员方法中定义静态成员变量和访问静态成员方法,就会出现以下错误:
a. non-static field ‘value’ cannot be referenced from a static context
filed指的是成员变量
非静态的成员变量不能在静态的上下文(静态方法的方法体)中被访问
non-static method cannot be referenced from a static context
非静态的成员变量不能在静态的上下文中被访问
非静态成员变量(非静态的成员方法),不能在静态上下文(静态方法的方法体)中被访问
为什么?
1) 之所以静态方法的方法体中,不能访问非静态成员变量,因为静态方法,优先于对象而存在.首先,我们可以在,没有任何对象存在情况下,就可以直接通过类名,运行静态方法.所以静态方法,是访问不到当前对象的普通成员变量值(因为此时,当前对象不存在)
2) 之所以静态方法方法体中,不能访问非静态的成员方法,因为,如果静态方法可以直接调用非静态的的方法。非静态的方法,可能去访问当前对象的成员变量值,而当前对象,此时有能还不存在。
b. 静态方法 or 非静态方法,方法体中都不能使用static关键字定义变量
为什么不能定义在非静态方法中?
static关键字意味着不依赖于对象而存在,与非静态方法的语义矛盾了,非静态方法本身是依赖于对象而存在的。
为什么不能定义在静态方法中
我们之前所写的方法都是静态方法,方法体中定义的变量属于局部变量,局部变量存储在栈上,而static变量存储在方法区中,和局部变量的内存分配矛盾
c. 静态方法的使用场景
静态方法和非静态方法除了访问方式不同,最大的区别,就是静态方法可以访问到的数据集合和非静态方法不同(静态方法方法体中,不能直接访问非静态的成员变量)
所以,通常,静态方法它所访问的数据:要么是静态的成员变量,要么是静态的成员方法
简单记:静态的只能访问静态的
通常,定义静态方法,都是为了,方别使用该方法的功能(工具方法), 让别人使用该方法的功能,为了方便使用该方法,通常,将这种工具方法定义为静态方法(访问的数据通常是方法参数),不用创建对象就可以使用
至于工具方法:例如:Arrays.toString();这个方法一定属于静态方法
静态成员变量和普通成员变量:
所属不同
静态变量属于类,所以也称为为 类变量
成员变量属于对象,所以也称为 实例变量(对象变量)
内存中的位置不同
静态变量存储于方法区的静态区
成员变量存储于堆内存
内存出现时间不同
静态变量先出现,成员变量后出现
静态变量随着类的加载而加载,随着类的消失而消失
成员变量随着对象的创建而存在,随着对象的消失而消失
调用不同
静态变量可以通过类名调用,也可以通过对象调用
成员变量只能通过对象名调用
························································································································································································
作业:
2. 写一个数组的工具类ArrayTool, 要求提供遍历,求最大值,最小值,逆置数组元素,查表(在数组中查找指定元素,若不存在,待查找元素返回-1,若存在返回元素在数组中首次出现的位置),找元素在int类型数组(int[])中最后出现的索引等操作。
提示:所谓工具类,就是一个类中定义的都是静态方法,这样的类称为工具类。工具类中定义的静态方法 就是工具方法,所谓工具方法,简单来说,就是该方法实现了一些公用的功能,为了方便使用,定义为工具方法
比如我们之前用过的Arrays.toString(数组),就是一个工具方法,工具方法处理的都是方法参数传递的数据。
比如定义一个查找数组最大值的方法,在工具类中就可以这样定义
class ArrayTool{
/*
查找数组中的最大值
*/
public static int max(int[] a) {
}
}
package com.cskaoyan;
/**
* @author shihao
* @create 2020-04-15 18:03
*/
class ArrayTool {
public static int findMin(int[] arr) {
int min = Integer.MAX_VALUE;
for (int i : arr) {
if (i < min)
min = i;
}
return min;
}
public static int findMax(int[] arr) {
int max = Integer.MIN_VALUE;
for (int i : arr) {
if (i > max)
max = i;
}
return max;
}
public static int[] reverse(int[] arr) {
int len = arr.length;
for (int i = 0; i < len / 2; i++) {
int temp = arr[i];
arr[i] = arr[len - 1 - i];
}
return arr;
}
public static int findFirst(int[] arr, int num) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == num)
return i;
}
return -1;
}
public static int findLast(int[] arr, int num) {
for (int i = arr.length - 1; i >= 0; i++) {
if (arr[i] == num)
return i;
}
return -1;
}
}
下一篇: 链表的增、删、查、找
推荐阅读