java关键字-static

1. static关键字

在java中,static可以用来修饰类,方法,变量,代码块。static修饰的方法,变量属于类,可以通过类直接调用,也可以通过类的对象来调用。static修饰的代码块在类加载的时候就会加载执行,主要用来初始化一些固定变量。
用static修饰就是为了在没有创建对象的情况下调用方法或者变量,以及静态代码块优化程序性能。

1.1 static修饰的类

普通类是不允许声明为静态的,只有内部类才可以。被static修饰的内部类就属于外部类本身,而不属于某各类的对象,可以直接作为一个普通类来使用。static关键字的作用是把类的成员变成类相关,就是static修饰的成员属于整个类而不是属于单个对象,外部类的上一级程序单元是包,所以不能使用static修饰。
静态内部类可以包含静态成员也可以包含非静态成员,静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。

public class StaticClass {
	private int stac1=5;
	private static int stac2=9;
	static class StaticInnerClass{
		//静态内部类可以包含静态成员
		private static int age;
		public void accessOuterStac(){
			//下面一行代码报错:Cannot make a static reference to the non-static field stac1
			//静态内部类无法访问外部类的实例变量
			System.out.println(stac1);
			System.out.println(stac2);
		}
	}
}

静态内部类是外部类的一个静态成员,因此外部类的所有方法,所有初始化块中都可以使用静态内部类来定义变量创建对象等,但是外部类依然不能直接访问静态内部类的成员,但可以使用静态内部类的类名作为调用者来访问静态内部类的类成员,也可以使用静态内部类对象作为调用者来访问静态内部类的实例成员,例如:

public class StaticClass {
	private int stac1=5;
	private static int stac2=9;
	static class StaticInnerClass{
		private static int age1 = 5;
		private int age2 = 9;
	}
	public void accessInnerProp(){
		System.out.println(StaticInnerClass.age1);
		System.out.println(new StaticInnerClass().age1);
	}
}

除此之外,java还允许在接口里边定义内部类,接口里边定义的内部类默认使用public static修饰,也就是说接口内部类只能是静态内部类。如果为接口内部类指定访问控制符,则只能是public,如果省略访问控制符,则该内部类默认是public修饰。

1.2 static修饰的方法

static方法一般称作静态方法,静态方法是属于累的,不依赖于任何对象就可以进行访问,所以对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,就是static修饰的方法不能访问没有static修饰的方法和变量,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。
  但是要注意的是,虽然在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法/变量的。例如:

public class StaticTest {
	private static String strA = "static property";//静态成员变量
	private String strB = "property";//非静态成员变量
	
	public StaticTest(){//无参构造函数
		
	}
	public void testStaticA(){//非静态方法
		/*
		 * 非静态方法可以访问静态成员变量和静态方法
		 */
		System.out.println(strA);
		System.out.println(strB);
		testStaticB();
	}
	public static void testStaticB(){//静态方法
		/*
		 * 静态方法可以访问静态成员变量,
		 * 但是不可以访问非静态方法和非静态成员变量
		 */
		System.out.println(strA);
		System.out.println(strB);//此处报错:Cannot make a static reference to the non-static field strB
		testStaticA();//此处报错:Cannot make a static reference to the non-static method testStaticA() from the type StaticTest
	}
	/*
	 * main方法是static修饰,所以可以访问静态成员。
	 * 如果要访问非静态成员,需要通过对象。
	 * main方法是程序的入口,在调用main方法是还没有产生类的对象,所以main方法要用static修饰
	 */
	public static void main(String[] args) {
		testStaticB();
		new StaticTest().testStaticA();
		System.out.println(strB);//不可以访问非静态成员,此处报错:Cannot make a static reference to the non-static field strB
	}
}

在上面的代码中,testStaticB方法用static修饰,是独立于对象存在的,可以直接用类名调用,在类初始化的时候根本就不存在strB变量,所以会报错。
而在testStaticB中调用testStaticA方法,此时根本就不知道testStaticA方法是否访问了非静态成员,也就是说有可能访问了非静态成员,但是此时根本不存在对象,也就没有非静态成员,就会造成编译错误。
而对于非静态成员方法,它访问静态成员方法/变量显然是毫无限制的。
如果想不创建对象就访问某个方法或者变量,那就用static修饰,大部分的工具类就是这样的.
我们最常见的static方法就是main方法,至于为什么main方法必须是static的,现在就很清楚了。因为程序在执行main方法的时候没有创建任何对象,因此只有通过类名来访问。
另外记住,即使没有显示地声明为static,类的构造器实际上也是静态方法。

1.3 static修饰的变量

在java语言中,变量可以分为成员变量和局部变量。
这里写图片描述
成员变量指的是在类里定义的变量,局部变量指的是在方法里定义的变量。
成员变量被分为类变量和实力变量两种,定义成员变量时没有用static修饰的就是实例变量,否则就是类变量,其中类变量从该类的准备阶段开始存在,直到系统销毁这个类,类变量的作用域与这个类的生存范围相同;而实例变量则从该类的实例被创建开始存在,直到系统完全销毁这个实例,实例变量的作用域与对应实例的生存范围相同。
用static修饰的变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
static成员变量的初始化顺序按照定义的顺序进行初始化。

1.4 static修饰的代码块

static关键字还有一个比较关键的作用就是用来形成静态代码块以优化程序性能。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。
static修饰的代码块与构造器的作用非常类似,就是对java对象进行初始化操作,所以被叫做初始化块,初始化块是java类里可以出现的地4中成员(成员变量,方法,构造器),一个类里可以有多个初始化块,初始化块的修饰符只能是static,被称为静态初始化块,也叫作类初始化快块,负责对类进行初始化,如果没有修饰符,是普通初始化块,负责对对象执行初始化。静态初始化块是类相关的,系统将在类初始化阶段执行静态初始化块,而不是在创建对象时才执行,因此静态初始化块总是比普通初始化块先执行,又比构造器先执行。静态初始化块不能对实例变量进行初始化处理。
static块可以用来优化程序性能,就是因为它的特性:只会在类加载的时候执行一次。例如:

import java.sql.Date;

public class StaticCodePerson {
	private Date birthDate;
    
    public StaticCodePerson(Date birthDate) {
        this.birthDate = birthDate;
    }
     
    boolean isBornBetween() {
    	//用来判断这个人是否是1946-1964年出生的,而每次isBornBetween被调用的时候,都会生成startDate和birthDate两个对象,造成了空间浪费
        Date startDate = Date.valueOf("1946");
        Date endDate = Date.valueOf("1964");
        return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;
    }
}

改成下面这样效率会更好:

import java.sql.Date;

public class StaticCodePerson {
	private Date birthDate;
    private static Date startDate,endDate;
    static{
    	//静态初始化块在类准备阶段就会初始化这两个变量
    	//而且只执行一次
        startDate = Date.valueOf("1946");
        endDate = Date.valueOf("1964");
    }
    
    public StaticCodePerson(Date birthDate) {
        this.birthDate = birthDate;
    }
     
    boolean isBornBetween() {
        return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;
    }
}

从上面两段代码可以看出,静态初始化块可以很大程度提高程序性能,因此很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。例如数据库连接的基本连接信息。
实际上,初始化块是一个假象,使用javac命令编译java类后,java类中的初始化块会消失–初始化块中代码会被还原到每个构造器中,并且位于构造器所有代码的前面。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java语言中的关键字是指具有特殊含义的单词,这些单词在Java程序中具有特定的用途,不能作为标识符或变量名使用。Java中共有50个关键字,其中包括48个保留关键字和2个特殊关键字。 以下是Java中的各种关键字: 1. abstract:用于定义抽象类和抽象方法。 2. assert:用于调试程序时进行断言判断,如果条件不成立将会抛出AssertionError异常。 3. boolean:用于定义布尔类型变量,只能取值true或false。 4. break:用于跳出循环语句。 5. byte:用于定义字节类型变量,取值范围为-128到127。 6. case:用于在switch语句中匹配选项。 7. catch:用于捕获异常。 8. char:用于定义字符类型变量。 9. class:用于定义类。 10. const:Java虽然保留了此关键字,但并没有使用,因此不能用于定义常量。 11. continue:用于跳过循环中的某个迭代。 12. default:用于switch语句中的默认选项。 13. do:用于定义do-while循环。 14. double:用于定义双精度浮点类型变量。 15. else:用于if语句中条件不成立时执行的代码块。 16. enum:用于定义枚举类型。 17. extends:用于继承一个类或实现一个接口。 18. final:用于定义常量或不可变的变量,或者修饰类、方法、变量等,表示其不可再被继承、重写或修改。 19. finally:用于定义无论是否有异常发生都需要执行的代码块。 20. float:用于定义单精度浮点类型变量。 21. for:用于定义for循环。 22. goto:Java虽然保留了此关键字,但并没有使用,因此不能跳转到标签。 23. if:用于定义条件语句。 24. implements:用于实现一个接口。 25. import:用于导入其他类的定义。 26. instanceof:用于判断一个对象是否属于某个类或实现了某个接口。 27. int:用于定义整型变量。 28. interface:用于定义接口。 29. long:用于定义长整型变量。 30. native:用于调用本地方法。 31. new:用于创建一个对象。 32. package:用于定义包。 33. private:用于定义私有成员,只能在当前类中访问。 34. protected:用于定义受保护的成员,只能在当前类及其子类和同一个包中访问。 35. public:用于定义公共成员,可以被任何类访问。 36. return:用于从方法中返回值。 37. short:用于定义短整型变量。 38. static:用于定义静态成员,只有一个拷贝,可以通过类名直接访问。 39. strictfp:用于声明浮点数计算具有严格的规范化行为。 40. super:用于引用父类的成员。 41. switch:用于定义switch语句。 42. synchronized:用于定义同步方法或同步代码块。 43. this:用于引用当前对象。 44. throw:用于抛出异常。 45. throws:用于声明方法可能抛出的异常。 46. transient:用于声明不需要持久化的变量。 47. try:用于定义异常处理代码块。 48. void:用于定义无返回值的方法。 49. volatile:用于声明变量是易变的,即每次访问都需要从主存中读取。 50. while:用于定义while循环。 以上就是Java中的各种关键字,这些关键字Java程序中起着非常重要的作用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值