2018.3.29
Static
静态成员变量
代码中的问题: 发现代码中,存在某一些成员变量的数值是一样的 大量重复 在每一个对象中都有存在,例如当前代码中的国家都是中国, 这样会占用过多的内存资源,甚至于硬盘资源。
期望: 把国家这个属性放到一个共享的区域里,然后让每一个对象使用就好。
解决问题: 使用Static关键字。
static关键字的使用:
1.如果使用static修饰的成员变量,这些成员变量称之为【静态成员变量】,这个静态成员变量存放在
实际存放的内存空间在【内存的数据区(静态区,共享区)】,【静态成员变量】和当前【类对象内存】的没有关系,这个【静态成员变量】
使用的内存空间 不在堆区内存对象中。
2.用static修饰的成员变量,这个【静态成员变量】可以提供给多个类对象使用。
3.什么时候用static。真正意义上存在大量重复的,并且存在一定共享基础的数据。这种情况下,可以使用
static修饰、。
eg.country适合用static修饰,name不适合。
【小问题】: 发现通过类对象来调用[静态成员变量],报警告 The static field Person.coutry should be accessed in a static way. 用static修饰【静态成员变量】应该用【静态】的方式访问。
【重点】: 用static修饰的成员变量,这个成员变量会【早于】类对象的创建而创建,而且【晚于】类对象的销毁而销毁。
所以用static修饰的【静态成员变量】和类对象"无关"。
严格来说通过类对象来调用静态成员变量是非法的。 java语言期望的是更加严谨的调用方式,因为和对象无关,所以不希望对象用来调用。
【推荐调用/使用成员变量的方式】
类名.成员变量;
没有警告,也是让你记得static修饰的【静态成员变量】和类对象无关。
【修改问题】 用static修饰的成员变量不管通过哪一种方式修改了内容,那么所有用到【静态成员变量】都会发生变动。
因为【静态成员变量】是一种【隐含的共享资源】。(讲到线程的时候很重要。)
例如:井里放块糖,有钱大家尝。
结果:
p1.country:中国
p2.country:中国
p3.country:prc
p4.country:中国
静态成员变量的使用案例---计数器
统计一个类创建类多少个对象。
人口统计,数据统计,ID的自动生成。
ID用创建对象之后,自动赋值,并且每一个对象的ID号是惟一的,递增的。
class Student {
private int id;//这个用来统计学生的id号。在项目中不允许变。考虑自动生成
private String name;
private char sex;
//在数据区的一个【静态成员变量】用于保存count的数据,而且私有化,不给类外提供任何的修改
//或者获取该数据的方式。
//如果程序停止,这里就会计数,没有做数据持久化操作,如实体化数据库保存。
private static int count =1;//代码没有问题
//private int count= 1;X
//构造代码块,任何一个对象都会执行的代码。
{
this.id=count++;
}
public Student() {
}
//因为id是通过当前程序自动生成的,不需要通过构造方法传参赋值
public Student(String name,char sex) {
this.name = name;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setSex(char sex) {
this.sex = sex;
}
public char getSex() {
return sex;
}
//id不希望外部能有修改的方式或者去哪先,所以封装之后不提供setter方法,只提供查看。
public int getId() {
return id;
}
}
public class Demo3 {
public static void main(String[] args) {
Student st1 = new Student();
System.out.println("id:"+st1.getId());
Student st2 = new Student();
System.out.println("id:"+st2.getId());
}
}
结果:
id:1
id:2
静态成员方法
Static 修饰成员方法,这个方法称之为【静态成员方法】
格式:
权限修饰符 +static+返回值类型+方法名(形参列表) {
方法体;
}
【重点】
用static修饰的成员方法,称之为【静态成员方法】,这个静态成员方法是早于对象的创建而【加载】,对象的销毁之后依然存在。
所以说【静态成员方法】和对象"无关"。
如果采用类对象调用【静态成员方法】会报警告;在Dog类里的【静态成员方法】sleep()应该用静态方式调用。
【注意事项】
1.用static修饰的静态成员方法中不能使用this关键字,
结果推论:
因为静态成员方法可以通过类名来调用,在用类名调用情况下,是不存在对象的,
而this关键字是用来表示调用该方法的对象关键字,这里不存在对象,所以不能用。
原理推论:
因为静态成员方法是早于对象加载,晚于对象销毁,所以和对象无关。
有没有对象,该方法都存在,所以this关键在在这里无法使用。
2.在Static修饰的【静态成员方法】中,不能直接调用非静态成员变量,因为【非静态成员变量】是保存在
类对象的堆区内存中,和类对象共存,而在【静态成员方法】的调用过程中是没有对象的。所以不能使用非静态成员变量。
3.【静态成员方法】中可以直接使用【静态成员变量】、
4.想在【静态成员方法】中使用【非静态成员变量】怎么办???
可以在当前【静态成员方法】中用new关键字,调用构造方法,创建一个对象,使用该对象。
案例:
单例设计模式。
【总结】:
静态对静态,非静态对非静态。
【静态成员方法用途】:
1.调用方便。通过类名直接调用该方法,无需借助于创建对象。
2.用来完成一些工具类。
Arrays 工具类。(里面没有成员变量,都用外部数据)
*/
class Dog {
//成员变量
private String name;
//[静态成员变量]
static String country = "jp";
//构造方法
public Dog() {
}
public Dog(String name) {
this.name = name;//jsp
}
//setter和getter
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
//成员方法
public void Run() {
this.name="11";//用this关键字来调用成员变量,this表示调用该方法的对象。、
name="1";//非静态成员变量
System.out.println("跑来跑去");
}
public static void Sleep() {
//this.name="11";cannot use this in static context. (why? )
country = "rb";//静态成员变量
//name = "1";X why报错。
System.out.println("睡你妹。");
}
public static void text() {
Dog dog = new Dog("gouzi");
System.out.println(dog.name);
}
}
public class Demo2 {
public static void main(String[] args) {
Dog dog = new Dog("liyangjing");
Dog.Sleep();//类名调用
Dog.text();
}
}
结果:
睡你妹
gouzi
Arrays工具类
/*
[静态成员方法的使用]
作成工具类,提供给开发者使用,更加便利,调用方便,摆脱类对象的约束,而且所有的数据
是调用者传入的和工具类的里面的成员变量无关,甚至于某些工具类是没有任何成员变量的。
Arrays工具类,提供了大量的数组操作的方法,而且在Arrays工具类里面所有的方法,都是
用public static修饰的。
sort toString binarySearch
* */
//展示数组里的数字、
public class Demo4 {
public static void main(String[] args) {
int[] arr = {1,5,3,4,2,8,9,10,7,6};
Arrays.sort(arr);
//使用一下Arrays工具类里面的sort方法。默认是从小到大,升序排列。
for(int i = 0;i<arr.length;i++) {
System.out.println(arr[i]);
}
//Arrays工具类里面的toString方法,方法的的返回值是一个String类型
//例如:{1, 2, 3} =>[1, 2, 3]
String arrString = Arrays.toString(arr);
System.out.println(arrString);
//Arrays 工具里面的binarySearch,是一个查找数据的方法,要求查找的数组数据必须是通过排序的。
//而且返回的是当前要找的数据所在下标,如果没有找到返回负数,找到返回有效下标值。
int index=Arrays.binarySearch(arr,5);
System.out.println("index="+index);
}
}
结果:
1
2
3
4
5
6
7
8
9
10
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
index=4