单例模式
饿汉单例模式
优点:没有加锁,执行效率会提高缺点:类加载时就初始化,浪费内存编程实现:私有构造器静态的私有属性公共的静态方法
懒汉单例模式
懒汉式:主要是针对饿汉式中不管是否需要使用对象都先创建对象所引起的内存浪费优点:由于采用延迟处理的方式,所以比较节约内存缺点:在多线程不能正常工作
静态static关键字
1、用于修饰成员
2、随着类加载,随着类消失
3、优先于对象,用类名直接访问
静态属性
static 属性是当前类的所有对象所共有的共同属性 ( 只有一个,而普通属性各个对象都有自己的,相互隔离) ,任何一个当前类对象修改这个属性,所有其他类对象的这个属性都会受影响典型应用:统计 A1 类的构建次数
执行顺序
静态属性--属性--构造器
package com.yan2;
public class Test2 {
public static void main(String[] args) {
//执行流程:静态属性---属性---构造器
A2 aa=new A2();
}
}
class A2 {
private C2 cc=new C2();
private static B2 bb=new B2();
public A2() {
System.out.println("构建A2对象....");
}
}
class B2 {
public B2() {
System.out.println("构建B2对象....");
}
}
class C2 {
public C2() {
System.out.println("构建C2对象....");
}
}
访问的方式
可以使用"类名.静态属性名"或者"对象名.静态属性名"的方式进行访问
package com.yan2;
public class Test1 {
public static void main(String[] args) {
A1 a1 = new A1();
A1 a2 = new A1();
a1.pp();
System.out.println(a1.count+"==="+a1.age);
System.out.println(a2.count+"==="+a2.age);
System.out.println(A1.count);//静态属性可以通过【类名称.属性名称】的方式进行访问
//当然也允许使用【对象名.属性名】的方式进行访问
}
}
class A1 {
public static int count = 0;//针对A1类的所有对象都共享同一个count属性
public int age = 0;
public void pp() {
count++;
age++;
}
}
定义常量
命名规则:名称全大写,下划线分词
声明语法: public static final double MIN_NUMBER = 0.1;声明的同时直接进行初始化先声明后在 static 静态块中赋值
package com.yan2;
//定义常量
public class Test3 {
public static void main(String[] args) {
System.out.println(A3.PI);
}
}
class A3 {
//命名规则:名称全大写,下划线分词
// final意思是一旦赋值则不允许修改
// static用于保证A3种不会存储多个
public final static double PI = 3.1415;
public final static int BB; //声明后并不是一定声明的同时进行赋值
static { //允许延迟到静态代码块种进行赋值
BB=110;
}
//不能在构造器种对常量进行延迟赋初始值
public A3() {
// BB=120;
}
}
静态方法
因为可以直接使用 ” 类名 . 方法名 ” 的形式直接调用静态方法,静态方法执行时很有可能并没有构建对象,所以在静态方法中不允许使用this/super 之类用于指定对象的关键字当然在静态方法中允许创建对象,并调用对象方法静态方法只能直接访问静态成员,不能直接访问非静态成员
static 关键字表明一个成员变量或者是成员方法可以在没有所属的类的实例变量的情况下被访问。Java 中 static 方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而 static 方法是编译时静态绑定的。static 方法跟类的任何实例都不相关,所以概念上不适用。
package com.yan2;
//静态方法
public class Test4 {
public static void main(String[] args) {
// 静态方法可以通过【类名.方法名(实参)】的方式进行调用
A4.test1();
// 静态方法也可以先创建对象,然后通过【对象名.方法名(实参)】的方式进行调用
A4 aa = new A4();
aa.test1(); // 会有警告信息
// 普通方法允许在子类种覆盖重新定义父类种的方法
C4 cc = new C4();
cc.pp1();
cc.pp2(); // 针对静态方法进行的覆盖定义
C4.pp2();// 如果C4种没有定义静态方法pp2则从父类B4种继承,如果定义了则使用自定义的静态方法
// Java中static方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而static方法是编译时静态绑定的。static方法跟类的任何实例都不相关,所以概念上不适用。
}
}
class A4 {
public static void test1() {
System.out.println("Test1方法...");
}
private int age;
private static int name;
// 静态方法只能直接访问静态成员,不能直接访问非静态成员
public static void test2() {
System.out.println(name);
System.out.println(age);
pp1();
// 如果需要访问非静态成员,则需要构建对象
A4 aa = new A4();
System.out.println(aa.age);
aa.pp1();
}
public void pp1() {
}
}
class B4 {
public void pp1() {
System.out.println("this is B4");
}
public static void pp2() {
System.out.println("this is B4...pp2");
}
}
class C4 extends B4 {
public void pp1() {
System.out.println("this is C4");
}
public static void pp2() {
System.out.println("this is C4...pp2");
}
}
静态块
类在执行时需要通过一个叫作类加载器的组件将程序加载到内存中,类在运行时一般不会发生变化,所以类不会频繁加载,在整个运行过程中只加载一次,而且常驻内存静态块在类加载完毕后自动执行,而且只执行一次
非静态块
非静态块在类内且在所有的方法之外,非静态块并不会在类加载后自动执行,而是在构建当前对象时自动执行。new 一次则会执行一次,执行时机在构造器之前执行
package com.yan2;
//静态块
public class Test5 {
public static void main(String[] args) throws Exception {
A5 aa= new A5();
// Class.forName("com.yan2.A5");
A5 ab=new A5();
}
}
/*
* 类在执行时需要通过一个叫作类加载器的组件将程序加载到内存中,
* 类在运行时一般不会发生变化,所以类不会频繁加载,在整个运行过
* 程中只加载一次,而且常驻内存
*
* 静态块在类加载完毕后自动执行,而且只执行一次
*/
class A5 {
// 静态块,没有覆盖定义
static {
System.out.println("A5...static");
}
// 非静态代码块
/* 非静态块在类内且在所有的方法之外,非静态块并不会在类加载后
* 自动执行,而是在构建当前对象时自动执行。new一次则会执行一
* 次,执行时机在构造器之前执行
*/
{
System.out.println("A5...Non-static");
}
//构造器
public A5() {
System.out.println("A5构造器");
}
static {
System.out.println("A2 static2");
}
}
静态导入
在一个类中反复使用到某个类中的静态方法,如果使用静态导入则在当前类中不需要再写类名称double a1=-12.345;System.out.println(Math.abs(a1));System.out.println(Math.cos(a1));System.out.println(Math.sin(a1));在 JDK5 当中提供了导入静态方法的 import 语句。语法:import static java.lang.Math.*; - 导入 Math 类中的所有静态方法注意要求使用JDK1.5+ 版本,否则编译不通过import static java . lang . Math . * ;public class Test1 {public static void main ( String [] args ) {double a1 = - 12.345 ;System . out . println ( abs ( a1 ));System . out . println ( cos ( a1 ));System . out . println ( sin ( a1 ));}}