3.6 static(静态)关键字

static关键字:

•  用于修饰成员(成员变量和成员函数)

被修饰后的成员具备以下特点:

•  随着类的加载而加载

•  优先于对象存在

•  被所有对象所共享

•  可以直接被类名调用

使用注意

•  静态方法只能访问静态成员

•  静态方法中不可以写this,super关键字

•  主函数是静态的

/*
static的特点:
1,static是一个修饰符,用于修饰成员。
2,static修饰的成员被所有的对象所共享。
3,static优先于对象存在,因为static的成员随着类的加载就已经存在了。 
4,static修饰的成员多了一种调用方式,就可以直接被类名所调用 。 类名.静态成员 。
5,static修饰的数据是共享数据,对象中的存储的是特有数据。

成员变量和静态变量的区别?
1,两个变量的生命周期不同。
	成员变量随着对象的创建而存在,随着对象的被回收而释放。
	静态变量随着类的加载而存在,随着类的消失而消失。

2,调用方式不同。
	成员变量只能被对象调用。
	静态变量可以被对象调用,还可以被类名调用。

3,别名不同。
	成员变量也称为实例变量。
	静态变量称为类变量。 

4,数据存储位置不同。
	成员变量数据存储在堆内存的对象中,所以也叫对象的特有数据.
	静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据.

静态使用的注意事项:
1,静态方法只能访问静态成员。(非静态既可以访问静态,又可以访问非静态)
2,静态方法中不可以使用this或者super关键字。
3,主函数是静态的。
*/

class Person {
	String name;// 成员变量,实例变量
	static String country = "CN";// 静态变量。类变量

	public void show() {
		System.out.println(Person.country + ":" + this.name);
	}
}

class StaticDemo {
	int num = 4;

	public static void main(String[] args) {
		// Person p = new Person();
		// p.name = "小强";
		// p.show();
		// System.out.println(p.country);
		// System.out.println(Person.country);
		// Person.show();
		new StaticDemo().show();
	}

	public void show() {
		System.out.println(num);
	}
}

静态内存图解

class Person {
	private String name;
	private int age;
	static String country = "CN";

	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public void show() {
		System.out.println(Person.country + ":" + this.name + ":" + this.age);
	}

	public static void method() {
		System.out.println(Person.country);
	}
}

class StaticDemo2 {
	public static void main(String[] args) throws Exception {
		Thread.sleep(5000);
		Person.method();

		Person p = new Person("java", 20);
		p.show();
	}
}

3.6 static(静态)关键字_第1张图片

/*
静态什么时候用?
1,静态变量。
	当分析对象中所具备的成员变量的值都是相同的 。
	这时这个成员就可以被静态修饰。
	只要数据在对象中都是不同的,就是对象的特有数据,必须存储在对象中,是非静态的。
	如果是相同的数据,对象不需要做修改,只需要使用即可,不需要存储在对象中,定义成静态的。

2,静态函数。
	函数是否用静态修饰,就参考一点,就是该函数功能是否有访问到对象中的特有数据。
	简单点说,从源代码看,该功能是否需要访问非静态的成员变量,如果需要,该功能就是非静态的。
	如果不需要,就可以将该功能定义成静态的。当然,也可以定义成非静态,
	但是非静态需要被对象调用,而仅创建对象调用非静态的
	没有访问特有数据的方法,该对象的创建是没有意义。

*/

class Demo {
	int age;
	static int num = 9;

	Demo(int age) {
		this.age = age;
	}

	public static void speak() {
		System.out.println(num);
	}

	public void show() {
		System.out.println(age);
	}

}

class StaticDemo3 {
	public static void main(String[] args) {
		// Demo d = new Demo(30);
		// d.speak();
		Demo.speak();

		// System.out.println("Hello World!");
	}
}

静态代码块和构造代码块

/*
静态代码块。
随着类的加载而执行。而且只执行一次。
作用:用于给类进行初始化。
不同于构造方法,构造方法是给对象初始化
不同于局部代码块,局部代码块是存在于方法中
 */
class StaticCode {
	static int num;
	static {
		num = 10;
		// num *=3;
		System.out.println("hahahah");
	}

	StaticCode() {
	}

	static void show() {
		System.out.println(num);
	}
}

class Person {
	private String name;
	{
		// 构造代码块。可以给所有对象进行初始化的。
		// 不同于构造方法,构造方法是给特定对象初始化
		// 不同于局部代码块,局部代码块是存在于方法中
		System.out.println("constructor code ");
		// cry();
	}

	static {
		System.out.println("static code");
	}

	Person()// 是给对应的对象进行针对性的初始化。
	{
		name = "baby";
		// cry();
	}

	Person(String name) {
		this.name = name;
		// cry();
	}

	public void cry() {
		System.out.println("哇哇");

	}

	public void speak() {
		System.out.println("name:" + name);
	}

	static void show() {
		System.out.println("show run");
	}
}

class StaticCodeDemo {
	static {
		// System.out.println("a");
	}

	public static void main(String[] args) {

		// Person p = null;
		// p.speak();

		// Person.show();
		// Person p1 = new Person();
		// p1.speak();
		// Person p2 = new Person("旺财");
		// p2.speak();
		// new Person();

		// new StaticCode().show();
		// new StaticCode().show();
		// StaticCode.show();
		// System.out.println("b");
	}
}

工具类将构造函数私有化

/**
 * 建立一个用于操作数组的工具类,其中包含着常见的对数组操作的函数如:最值,排序等 。
 * 
 */

public class ArrayTool {
	
	// 该类中的方法都是静态的,所以该类是不需要的创建对象的。为了保证不让其他成创建该类对象
	// 可以将构造函数私有化。
	private ArrayTool() {
	}

	/**
	 * 获取整型数组的最大值。
	 * @param arr 接收一个元素为int类型的数组。
	 * @return 该数组的最大的元素值
	 */
	public static int getMax(int[] arr) {
		int maxIndex = 0;
		for (int x = 1; x < arr.length; x++) {
			if (arr[x] > arr[maxIndex])
				maxIndex = x;//
		}
		return arr[maxIndex];
	}

	/**
	 * 对数组进行选择排序。
	 * @param arr 接收一个元素为int类型的数组。
	 */
	public static void selectSort(int[] arr) {
		for (int x = 0; x < arr.length - 1; x++) {
			for (int y = x + 1; y < arr.length; y++) {
				if (arr[x] > arr[y])
					swap(arr, x, y);
			}
		}
	}

	/*
	 * 用于给数组进行元素的位置置换。
	 * @param arr 接收一个元素为int类型的数组。
	 * @param a
	 * @param b
	 */
	private static void swap(int[] arr, int a, int b) {
		int temp = arr[a];
		arr[a] = arr[b];
		arr[b] = temp;
	}

	/**
	 * 获取指定的元素在指定数组中的索引.
	 * @param arr 接收一个元素为int类型的数组。
	 * @param key 要找的元素。
	 * @return 返回该元素第一次出现的位置,如果不存在返回-1.
	 */
	public static int getIndex(int[] arr, int key) {
		for (int x = 0; x < arr.length; x++) {
			if (arr[x] == key)
				return x;
		}
		return -1;
	}

	/**
	 * 将int数组转换成字符串。格式是:[e1,e2,...]
	 * @param arr 接收一个元素为int类型的数组。
	 * @return 返回该数组的字符串表现形式。
	 */
	public static String arrayToString(int[] arr) {
		String str = "[";
		for (int x = 0; x < arr.length; x++) {
			if (x != arr.length - 1)
				str = str + arr[x] + ", ";
			else
				str = str + arr[x] + "]";
		}
		return str;
	}
}
class ArrayToolDemo 
{
	public static void main(String[] args) 
	{
		int[] arr = {4,8,2,9,72,6};
//		ArrayTool tool = new ArrayTool();
//		int max= ArrayT8ool.getMax(arr);
//		System.out.println("max="+max);
		int index = ArrayTool.getIndex(arr,8);
		System.out.println("index="+index);
	}
}

单例模式

/*
设计模式:对问题行之有效的解决方式。其实它是一种思想。

1,单例设计模式。
解决的问题:就是可以保证一个类在内存中的对象唯一性。

比如对于多个程序使用同一个配置信息对象时,就需要保证该对象的唯一性。

如何保证对象唯一性呢?
1,不允许其他程序用new创建该类对象。
2,在该类创建一个本类实例。
3,对外提供一个方法让其他程序可以获取该对象。

步骤:
1,私有化该类构造函数。
2,通过new在本类中创建一个本类对象。
3,定义一个公有的方法,将创建的对象返回。
*/

//饿汉式
class Single// 类一加载,对象就已经存在了。
{
	private static Single s = new Single();

	private Single() {
	}

	public static Single getInstance() {
		return s;
	}
}

// 懒汉式
class Single2// 类加载进来,没有对象,只有调用了getInstance方法时,才会创建对象。
			// 延迟加载形式。
{
	private static Single2 s = null;

	private Single2() {
	}

	public static Single2 getInstance() {
		if (s == null)
			s = new Single2();
		return s;
	}
}

class SingleDemo {
	public static void main(String[] args) {
		Single s1 = Single.getInstance();
		Single s2 = Single.getInstance();
		System.out.println(s1 == s2);
		// Single ss = Single.s;
		// Test t1 = new Test();
		// Test t2 = new Test();
		Test t1 = Test.getInstance();
		Test t2 = Test.getInstance();
		t1.setNum(10);
		t2.setNum(20);
		System.out.println(t1.getNum());
		System.out.println(t2.getNum());
	}
}

class Test {
	private int num;

	private static Test t = new Test();

	private Test() {
	}

	public static Test getInstance() {
		return t;
	}

	public void setNum(int num) {
		this.num = num;
	}

	public int getNum() {
		return num;
	}

}

3.6 static(静态)关键字_第2张图片

你可能感兴趣的:(3.6 static(静态)关键字)