一、static

静态变量和静态方法

static关键字最基本的用法是:

1、被static修饰的变量属于类变量,可以通过类名.变量名直接引用,而不需要new出一个对象来

2、被static修饰的方法属于类方法,可以通过类名.方法名直接引用,而不需要new出一个对象来

被static修饰的变量、被static修饰的方法统一属于类的静态资源,是类实例之间共享的,换言之,一处变、处处变

静态资源属于类,但是是独立于类存在的。从JVM的类加载机制的角度讲,静态资源是类初始化的时候加载的,而非静态资源是类new的时候加载的。类的初始化早于类的new。

问题:

1、静态方法能不能引用非静态资源?不能,new的时候才会产生的东西,对于初始化后就存在的静态资源来说,根本不认识它。

2、静态方法里面能不能引用静态资源?可以,因为都是类初始化的时候加载的,大家相互都认识。

3、非静态方法里面能不能引用静态资源?可以,非静态方法就是实例方法,那是new之后才产生的,那么属于类的内容它都认识。

静态块

和静态变量、静态方法一样,静态块里面的代码只执行一次,且只在初始化类的时候执行

结论:

①静态资源的加载顺序是严格按照静态资源的定义顺序来加载的。

②静态代码块对于定义在它之后的静态变量,可以赋值,但是不能访问。

③静态代码块是严格按照父类静态代码块->子类静态代码块的顺序加载的,且只加载一次。

什么是static,static的含义是什么?

1.静态:当一个成员变量被static修饰的时候,在保存的一瞬间,会将成员变量(方法)分配到静态域中进行保存,并且占用内存。
2.类访问:被static修饰的内容属于类,不被static修饰的内容属于对象。当调用被static修饰的内容时,需要通过类名.去调用,不被static修饰的内容需要通过对象.去调用。

static能够修饰的内容?

1.成员变量(局部变量不可以被static修饰)
2.方法(构造方法不能被static修饰)
3.代码块
4.内部类(类不可以被static修饰)

栈和堆的区别?

栈(stack):存放的是局部变量和地址
堆(heap):存放的是成员变量和new出来的东西(对象)

二、final

final能修饰哪些内容?

1.变量 2.方法 3.类

final有哪些特点?

1.final修饰的变量叫做常量,常量必须赋默认值,并且值不可改。
2.final修饰的方法不可以被重写
3.final修饰的类不能被继承

面试笔试重点:
	final Test TEST=new Test();
	int age=10;
(1)TEST =new Test();有没有错? 有错,因为被final修饰,所以对象不可改(地址不可改)
(2)TEST.age++;有没有错? 没错,因为age没有被final修饰,所以值可改。

对于被static和final修饰过的实例常量,实例本身不能再改变了,但对于一些容器类型(比如,ArrayList、HashMap)的实例变量,不可以改变容器变量本身,但可以修改容器中存放的对象,这一点在编程中用到很多。

import java.util.ArrayList;
import java.util.HashMap;

public class FinalTest {

    private static final ArrayList<String> list = new ArrayList<String>();
    private static final HashMap<String,String> map = new HashMap<String,String>();

    public static void main(String[] args) {
        list.add("aaa");//正确,容器变量本身没有变化,但存放内容发生了变化。
        list.add("bbb");
        System.out.println("list=" + list + "\r\n");

        map.put("a","a");
        map.put("b","b");
        System.out.println("map=" + map + "\r\n");
    }
}

abstract可以与final连用吗?

不可以

一个abstract类不可以被声明为final类 。正确。抽象类需要被继承才能使用,而被final修饰的类无法被继承,所以abstract和final是不能共存的。

①Java抽象类是内部类时,可以被private修饰 
②Java抽象类不是内部类时,不可以被private修饰 

声明为final的方法是可以重载,但是在子类中不可以被重写。

三、volatile

作用:保证内存可见性

JAVA的内存模型

java 中静态的东西能实例化吗_成员变量

 如上图所示,所有线程的共享变量都存储在主内存中,每一个线程都有一个独有的工作内存,每个线程不直接操作在主内存中的变量,而是将主内存上变量的副本放进自己的工作内存中,只操作工作内存中的数据。当修改完毕后,再把修改后的结果放回到主内存中。每个线程都只操作自己工作内存中的变量,无法直接访问对方工作内存中的变量,线程间变量值的传递需要通过主内存来完成。 

上述的Java内存模型在单线程的环境下不会出现问题,但在多线程的环境下可能会出现脏数据,例如:如果有AB两个线程同时拿到变量i,进行递增操作。A线程将变量i放到自己的工作内存中,然后做+1操作,然而此时,线程A还没有将修改后的值刷回到主内存中,而此时线程B也从主内存中拿到修改前的变量i,也进行了一遍+1的操作。最后A和B线程将各自的结果分别刷回到主内存中,看到的结果就是变量i只进行了一遍+1的操作,而实际上A和B进行了两次累加的操作,于是就出现了错误。究其原因,是因为线程B读取到了变量i的脏数据的缘故。

volatile关键字作用:保证内存可见性。意思就是被volatile修饰的变量每次取的值都是内存最新的数据。

volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。

volatile 修饰符,主要用于线程的编程。

后续补充