static:可以修饰 java类、方法、变量、代码块的方法
static修饰类时,这个类不能是普通的类,只能是内部类。具体使用:
public class StaticDemo1 {
public static class InnerClass {
InnerClass() {
System.out.println("===========静态内部类=============");
}
public void InnerMethod() {
System.out.println("===========静态内部类的方法==========");
}
}
public static void main(String[] args) {
InnerClass innerClass = new InnerClass();
innerClass.InnerMethod();
}
}
/*
输出结果:
===========静态内部类=============
===========静态内部类的方法==========
*/
内部类不用static修饰时写法:
public class StaticDemo11 {
public class InnerClass {
InnerClass() {
System.out.println("===========内部类=============");
}
public void innnerMethod() {
System.out.println("===========内部类的方法=======");
}
}
public static void main(String[] args) {
InnerClass innerClass = new StaticDemo11().new InnerClass();
innerClass.innnerMethod();
}
}
/*
输出:
===========内部类=============
===========内部类的方法=======
*/
结论:
如果没有用static修饰InnerClass,则只能先new一个外部实例,再通过外部实例创建内部类对象。
修饰方法的时候,其实跟类一样,可以直接通过类名来进行调用:
public class StaticDemo2 {
public static void staticMethod2() {
System.out.println("========静态方法========");
}
public static void main(String[] args) {
// 方式1、通过类名调用
// StaticDemo2.staticMethod();
// 方式2、创建对象调用
StaticDemo2 demo2 = new StaticDemo2();
demo2.staticMethod2();
}
}
/*
输出:
========静态方法========
*/
**结论:**调用有两种方式,一般选择方式一
注意:静态方法不能调用非静态成员。
被static修饰的成员变量叫做静态变量,也叫做类变量,说明这个变量是属于这个类的,而不是属于是对象,没有被static修饰的成员变量叫做实例变量,说明这个变量是属于某个具体的对象的。
public class StaticDemo3 {
public static String string = "静态变量";
public static void main(String[] args) {
// 直接通过类名称调用
System.out.println(StaticDemo3.string);
}
}
/*
输出:
StaticDemo1
*/
**结论:**可以直接通过类名称调用
public class StaticDemo5 {
static int value = 33;
public static void main(String[] args) {
new StaticDemo5().printValue();
}
private void printValue() {
int value = 3;
System.out.println(this.value);
}
}
大家猜猜这里输出会是多少呢?这里主要考察了this和static的理解。this代表的是当前对象, 那么通过new Main()来调用printValue的话,当前对象就是通过new Main()生成的对象 。 而static变量是被对象所享有的,因此在printValue中的this.value的值毫无疑问是33 。 在这里永远要记住一点:静态成员变量虽然独立于对象,但是不代表不可以通过对象去访问,所有的静态方法和静态变量都可以通过对象访问(只要访问权限足够)。
静态代码块在类第一次被加载的时候执行。
类的初始化顺序:先父类后子类
详细过程:
父类静态变量、父类静态代码块
子类静态变量、子类静态代码块
父类普通变量、父类普通代码块、父类构造函数
子类普通变量、子类普通代码块、子类构造函数
静态块里面的代码只执行一次,且只在初始化类的时候执行 。
代码验证:
public class Fu {
//父类静态代码块
static {
System.out.println("=====父类静态代码块=====");
}
// 父类构造函数
Fu() {
System.out.println("=====父类构造函数=======");
}
public static void main(String[] args) {
new Zi();
new Zi();
}
}
class Zi extends Fu {
// 子类静态代码块
static {
System.out.println("=====子类静态代码块=====");
}
Zi() {
System.out.println("====子类构造函数=====");
}
}
/*
输出:
=====父类静态代码块=====
=====子类静态代码块=====
=====父类构造函数=======
====子类构造函数=====
=====父类构造函数=======
====子类构造函数=====
*/
静态代码块需要注意的问题:
public class StaticDemo4 {
static {
c = 10;
System.out.println(c);
}
public StaticDemo4() {
System.out.println(c);
}
public static void main(String[] args) {
new StaticDemo4();
}
private static int c;
}
如果将private static int c;
这行代码放到static静态代码块之前就为正确的
1、static是一个修饰符,用于修饰成员。(成员变量,成员函数)static修饰的成员变量 称之为静态变量或类变量。
2、static修饰的成员被所有的对象共享。
3、static优先于对象存在,因为static的成员随着类的加载就已经存在。
4、static修饰的成员多了一种调用方式,可以直接被类名所调用,(类名.静态成员)。
5、static修饰的数据是共享数据,对象中的存储的是特有的数据。
1、下面这段代码的输出结果是什么?
public class Test extends Base{
static{
System.out.println("test static");
}
public Test(){
System.out.println("test constructor");
}
public static void main(String[] args) {
new Test();
}
}
class Base{
static{
System.out.println("base static");
}
public Base(){
System.out.println("base constructor");
}
}
输出结果:
base static
test static
base constructor
test constructor
分析:
先找到main方法入口, main方法是程序入口,但在执行main方法之前,要先加载Test类
加载Test类的时候,发现Test类继承Base类,于是先去加载Base类
加载Base类的时候,发现Base类有static块,而是先执行static块,输出base static结果
Base类加载完成后,再去加载Test类,发现Test类也有static块,而是执行Test类中的static块,输出test static结果
Base类和Test类加载完成后,然后执行main方法中的new Test(),调用子类构造器之前会先调用父类构造器
调用父类构造器,输出base constructor结果然后再调用子类构造器,输出test constructor结果
然后再调用子类构造器,输出test constructor结果
2、 这段代码的输出结果是什么?
public class Test {
Person person = new Person("Test");
static{
System.out.println("test static");
}
public Test() {
System.out.println("test constructor");
}
public static void main(String[] args) {
new MyClass();
}
}
class Person{
static{
System.out.println("person static");
}
public Person(String str) {
System.out.println("person "+str);
}
}
class MyClass extends Test {
Person person = new Person("MyClass");
static{
System.out.println("myclass static");
}
public MyClass() {
System.out.println("myclass constructor");
}
}
输出结果:
test static
myclass static
person static
person Test
test constructor
person MyClass
myclass constructor
分析:
new MyClass()
,执行此代码之前,先加载MyClass类,发现MyClass类继承Test类,而是要先加载Test类,Test类之前已加载Person person = new Person("Test")
执行Person构造器,输出person Test结果总结:
把握住一个思路:执行过程
父类静态变量、父类静态代码块
子类静态变量、子类静态代码块
父类普通变量、父类普通代码块、父类构造函数
子类普通变量、子类普通代码块、子类构造函数
3、这段代码的输出结果是什么?
public class Test {
static{
System.out.println("test static 1");
}
public static void main(String[] args) {
}
static{
System.out.println("test static 2");
}
}
结果:
test static 1
test static 2
分析: