java的单例、static修饰符及static的继承

单例设计模型:

static修饰符:

①:static静态只有一份(同一个虚拟机中) (节省资源),类代码被装载内存时,静态代码分配内存,并执行,并且常驻内存。

可参考:类加载顺序

②:Static修饰成员变量,成为"类变量",属于整个类,类的共享变量。注:不能修饰局部变量。

         static是一块为整个类共有一块存储区域,静态变量只有一份,值变化后,所有访问值变化生效。

         java中用类名调用static变量和方法(对象调用也可以):类名.变量(方法名)

③:static修饰类方法,属于类方法,继承中子类可以定义相同方法,静态不支持覆盖,此时不存在继承间的多态。

④:static静态块(定义和方法平行),在类加载时执行一次,以后不再执行,一般用于初始化静态成员。

④:类的方法继承与否取决于4大访问修饰符,和static修饰符无关(static不会发生继承多态)。

        注:main()主方法定义成static,是因为加载类代码入内存的时候还没有对象这个概念。

类A:

package ca.singleton;

public class A {
	//static属性
	public static int a = 5;
	//实例变量
	public int b = 3;
	public static String c;
	//静态块
	static{
		c="initial c field";
	}
	//静态方法
	public static void print(){
		System.out.println("A static print method");
	}
	//实例方法
	public void display(){
		System.out.println("A instance display method");
	}
}

类B继承A:

package ca.singleton;

public class B extends A{
	//static属性
	public static int a = 2;
	//实例变量
	public int b = 8;
	public static String c;
	//静态块
	static{
		c="initial xxxxx";
	}
	//静态方法
	public static void print(){
		System.out.println("B static print method");
	}
	//实例方法
	public void display(){
		System.out.println("B instance display method");
	}
	public static void main(String[] args) {
		B b = new B();
		A a = new B();
		//call static print method
		b.print();
		a.print();
		//call instance display method
		b.display();
		a.display();
		//field static
		System.out.println(b.a);
		System.out.println(a.a);
		//field instance
		System.out.println(b.b);
		System.out.println(a.b);
		//static block
		System.out.println(b.c);
		System.out.println(a.c);
	}
}

输出结果为:

B static print method
A static print method
B instance display method
B instance display method
2
5
8
3
initial xxxxx
initial c field

static继承:

从上面执行结果,可以反映出:

①:静态属于所有它的类,不会被继承。

②:类的继承层次模型下的多态只发生在方法(成员方法)上。

③:类的成员属性,以及静态变量,静态方法,静态块,都不发生继承。

Singleton模型:
Static通常用于单例设计,Singleton是一种设计模式,高于语法,可以保证一个类在整个系统中(同一个虚拟机中)仅有一个对象。

在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例,具有资源管理器功能。

单例类原则:  ①只有一个实例对象;  ②自己创建自己的这一个对象;  ③通过方法提供仅有的对象给其他对象使用。

                  综之:  单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

实现的三种方式:

1:饿汉式单例

package ca.singleton;
/**
 * 饿汉式单例类
 * 单例类被第一次装载入内存时候,已经产生了单例对象
 * */
public class SingletonA {
	//在类初始化时(装载类时,非new),单例对象,已经被初始化
	private static SingletonA instance = new SingletonA();
	//默认构造方法为私有,防止其他地方实例化
	private SingletonA(){}
	//静态工厂方法,对外提供获取单例对象的获取接口
	/**
	 * 获取SingletonA类的单例对象
	 * */
	public static SingletonA getInstance(){
		return instance;
	}
}

2:懒汉式单例类

package ca.singleton;
/**
 * 懒汉式单例类
 * 延迟(懒)加载,在第一次调用getInstance()方法获取单例对象的时候创建单例对象
 * */
public class SingletonB {
	//其他类第一次获取单例对象时候创建
	private static SingletonB instance = null;
	//默认构造方法为私有,防止其他地方实例化
	private SingletonB(){}
	//静态工厂方法,对外提供获取单例对象的获取接口
	/**
	 * 获取SingletonB类的单例对象
	 * */
	public synchronized static SingletonB getInstance(){
		if(instance == null){
			instance = new SingletonB();
		}
		 return instance;
	}
}

3:登记式单例类

package ca.singleton;

import java.util.HashMap;
import java.util.Map;

/**
 * 登记式单例类
 * 使用类名注册,下次直接从里面获取
 * */
public class SingletonC {
	//登记类,键值对(类名- 类对象)保存map   ?if SingletonC = Object
	private static Map<String, SingletonC> map = new HashMap<String, SingletonC>();
	//提供protected的默认构造方法, 同包或子类可见
	protected SingletonC() {}
	//注册当前类的对象到map
	static{
		SingletonC scInstance = new SingletonC();
		map.put(scInstance.getClass().getName(), scInstance);
	}
	/**
	 * 静态工厂方法,返回类在map中被登记的唯一实例
	 * */
	public static SingletonC getInstance(String name){
		//name输入为空,使用当前类名称
		if(name == null){
			name = SingletonC.class.getName();
			System.out.println("name is null,name to "+name);
		}
		//name类名对应的对象未被登记到map
		if(map.get(name) == null){
			try {
				map.put(name,(SingletonC) Class.forName(name).newInstance());
			} catch (InstantiationException e) {
				System.out.println("Instantiation Exception"+e);
			} catch (IllegalAccessException e) {
				System.out.println("Illegal Access Exception"+e);
			} catch (ClassNotFoundException e) {
				System.out.println("Class Not Found Exception"+e);
			}
		}
		return map.get(name);
	}
	//一个示意性的商业方法???
	public String about(){
		return "Hello,I am a schematic of the commercial method";
	}
}

singletonD继承singletonC:

package ca.singleton;

public class SingletonD extends SingletonC{

}

测试类:

package ca.singleton;

public class SingleTest extends A {
	public static void main(String[] args) {
		//
		SingletonA s1 = SingletonA.getInstance();
		SingletonA s2 = SingletonA.getInstance();
		String ss = s1==s2 ? "1&2 T" : "1&2 F";
		System.out.println(ss);
		//
		SingletonB s3 = SingletonB.getInstance();
		SingletonB s4 = SingletonB.getInstance();
		System.out.println(s3==s4 ? "3&4 T" : "3&4 F");
		//
		SingletonC s5 = SingletonC.getInstance(null);
		SingletonC s6 = SingletonC.getInstance(null);
		System.out.println(s5==s6 ? "5&6 T" : "5&6 F");
		System.out.println(s5.about());

		SingletonD s7 = (SingletonD) SingletonC.getInstance("ca.singleton.SingletonD");
		SingletonD s8 = (SingletonD) SingletonC.getInstance("ca.singleton.SingletonD");
		System.out.println(s7==s8 ? "7&8 T" : "7&8 F");
		System.out.println(s7.about());
		System.out.println(s5==s7 ? "5&7 T" : "5&7 F");
	}
}

输出结果为:

1&2 T
3&4 T
name is null,name to ca.singleton.SingletonC
name is null,name to ca.singleton.SingletonC
5&6 T
Hello,I am a schematic of the commercial method
7&8 T
Hello,I am a schematic of the commercial method
5&7 F

从上面执行结果,可以反映出:

使用“==”比较,基本类型,引用存储空间直接存储的真实值,所以比较的值;

对于其他类类型,在任何时候“==”比较的都是地址,这种比较永远不会被覆盖。

可以看出上边的单例都存在一个对象。

如果想让高并发下多线程在单例中生效,就要保证单例对象操作的方法为线程同步(对象锁)。

时间: 2024-09-01 02:01:08

java的单例、static修饰符及static的继承的相关文章

方法-求问:java里面static修饰符作用

问题描述 求问:java里面static修饰符作用 static作用具体是什么,非static作用又是什么,static修饰方法和属性分别是什么效果,具体点谢谢 解决方案 static 是全局变量, 如 static int c=0; c=c+1; 那么这变量,就是一个全局变量, 每一次改变它都会执行,但是再给它赋值 就会报错 再这样写 c=5; 系统就会报错. 解决方案二: static修饰的成员变量或者成员函数,是直接通过类名来访问的,不需要实例化的. 而非静态的成员方法的访问需要通过实例化

Java编程那些事儿65——static修饰符

修饰符的作用是让被修饰的内容具备特定的功能,在程序中合理使用修饰符可以在语法和功能上实现很多需要的效果.Java语言中的修饰符主要有5个:static.final.native.abstract和synchronized.这里首先讲解static.final和native的作用. 8.7.1 static修饰符 static关键字的中文意思是静态的,该修饰符可以修饰成员变量,成员常量和成员方法.使用该关键字修饰的内容,在面向对象中static修饰的内容是隶属于类,而不是直接隶属于对象的,所以st

Java语言入门教程(六):Java语言中的static修饰符

在Java类中,我们常常会看到static关键字,往往被称为静态的.Static修 饰符可以用来修饰数据成员,方法成员,但是不能修饰类(此处指外部类),不 能修饰构造方法.如: package com.csst.vo; public class User { private String name; private static int count; public String getName() { return name; } public void setName(String name)

Java修饰符 abstract,static,final 的区别详解_java

static 表示静态,它可以修饰属性,方法和代码块. 1.static修饰属性(类变量),那么这个属性就可以用类名.属性名来访问,也就是使这个属性成为本类的类变量,为本类对象所共有.这个属性就是全类公有.(共有的类变量与对象无关,只和类有关). 类加载的过程,类本身也是保存在文件中(字节码文件保存着类的信息)的,java会通过I/O流把类的文件(字节码文件)读入JVM(java虚拟机),这个过程成为类的加载.JVM(java虚拟机)会通过类路径(CLASSPATH)来找字节码文件. 类变量,会

static 成员变量-成员变量的问题 static修饰符

问题描述 成员变量的问题 static修饰符 为什么成员变量s前面一定要加static,否则就报错 解决方案 这个道理很简单,实例变量是每个对象实例都有的,而静态方法是一个类才有一个的. 看下面的代码 class Test { public int i; static void foo() { println(i); } } 我们假设这代码是可以编译的 看如下调用 Test t1 = new Test(); t1.i = 1; Test t2 = new Test(); t2.i = 2; Te

详解Java编程中protected修饰符与static修饰符的作用_java

protected 来谈谈protected访问权限问题.看下面示例1: Test.java class MyObject {} public class Test { public static void main(String[] args) { MyObject obj = new MyObject(); obj.clone(); // Compile error. } } 此时出现上文提到的错误:The method clone from the type Object is not v

修饰符-public static void main(String[] args)

问题描述 public static void main(String[] args) 本人初学者,public static void main(String[] args) 这句代码中的 修饰符及参数总是不理解,请大神解答.谢谢!!! 解决方案 public static void main(String[] args) public 这是一个公有的方法 static 这是一个静态的方法 void 没有返回值 main 方法名 String[] args,这是参数,程序运行的时候可以加上参数

Java 实现单例的难点

有简单又高效的方法可以实现单例模式,但没有一种方式能在任何情况下都确保单例的完整性. 单例模式是指某个类只被实例化一次,用来表示全局或系统范围的组件.单例模式常用于日志记录.工厂.窗口管理器和平台组件管理等.我认为要尽量避免 使用单例模式,因为一旦实现就很难改变或重载,而且会造成编写测试用例困难.代码结构糟糕等问题.另外,下面文章中的单例模式是不安全的. 人们花大量的精力研究怎样更好地实现单例模式,但有一种简单高效的实现方法.然而,没有一种方法能在任何情况下都确保单例的完整性.阅读下文,看看你是

举例详解Java中的访问权限修饰符_java

访问权限符:(1)public: 对于成员来说:任何其他类都可以访问它们,不管在同一个包中还是在另外的包中. 对于类来说:    也是一样.(2)friendly: 对于成员老说:如果一个类的成员没有任何权限修饰,那么它门就是缺省包访问权限,用friendly来表示,注 意friendly不是Java中的关键字,这里是个人喜欢的方式用它表示而已.同一个包内其它类可以访问,但包外 就不可以.对于同一个文件夹下的.没有用package的classes,Java会自动将这些classes初见为隶属于该