1、static
1.1、static的基本使用
1、static关键字介绍
总结:方便在没有创建对象的情况下进行调用。 也就是说,static修饰的不需要创建对象去调用,直接根据类名就可以去调用。 因为静态变量随着类加载时被完成初始化,他们在内存中仅有一个,且JVM也会只为他们分配一次内存。 使用场景:对象之间共享数据,方便访问。
2、static的使用方法:
static一般用来修饰成员变量或方法(有一种特殊的用法,用static修饰内部类,普通类时不允许声明位静态的)。
2.1、static修饰内部类:
public class Test3 {
public static class InnerClass {
InnerClass(){
System.out.println("============静态内部类");
}
public void InnerMethod(){
System.out.println("============静态内部方法");
}
}
public static void main(String[] args) {
//直接通过Test3类名访问静态内部类InnerClass
InnerClass inner = new Test3.InnerClass();
//调用方法
inner.InnerMethod();
}
}
结果:
============静态内部类
============静态内部方法
2.2、static关键字修饰方法
修饰方法的时候,跟类一样,直接可以通过类名来进行调用。
2.3、static关键字修饰变量
被static修饰的成员变量叫做静态变量,也叫做类变量,说明这个变量时属于这个类的,而不是属于对象。没有被static修饰的成员变量叫做实例变量,说明这个变量时数据某个具体的对象。
2.4、static关键字修饰代码块
3、static关键字修饰的执行顺序
父类静态变量--父类静态代码块--子类静态变量--子类静态代码块--父类普通变量--父类普通代码块--父类构造函数--子类普通变量--子类普通代码块--子类构造函数。
1.2、深入理解static关键字
从上图中我们可以发现,静态变量存放在方法区,并且是被所有线程所共享。 解释一下上图的区域。
堆区: 1、存储的全部是对象,每一个对象都包含一个与之对应的Class的信息。 2、JVM只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身。
栈区: 1、每一个线程包含一个栈区,栈中只保存基本数据类型的对象和自定义对象的引用。 2、每一个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。 3、栈区分为3部分:基本类型变量区、执行环境上下文,操作指令区(存放操作指令)。
方法区: 1、又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。 2、方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。
1.3、总结
特点: 1、static是一个修饰符,用于修饰成员(成员变量,成员函数,还有内部类)。 2、static修饰的成员被所有的对象共享。 3、static优先于对象存在,因为static的成员随着类的加载而加载。 4、static修饰的成员多了一种调用方式,可以直接被类名所调用。 5、static修饰的数据是共享数据,对象中的存储时特有的数据。
成员变量和静态变量的区别: 1、生命周期不同: 成员变量随着对象的创建而存在随着对象的回收而释放。 静态变量随着类的加载而存在随着类的消失而消失。 2、调用方式 成员变量只能被对象调用。 静态变量可以被对象调用,也可以用类名调用。(推荐用类名调用) 3、别名不用 成员变量也称为实例变量。 静态变量称为类变量。 4、数据存储位置不同 成员变量数据存储在堆内存的对象中,所以也叫对象的特有数据。 静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据。
静态使用时需要注意的事项 1、静态方法只能访问静态成员。(非静态既可以访问静态,又可以访问非静态) 2、静态方法中不可以使用this或者super关键字。 3、主函数是静态的。
1.4、考点static
问题一:static出现的位置
public class Test3 {
static String x = "1";
static int y =1;
public static void main(String[] args) {
static int z = 2;//static不应该出现在这里编译有错误
System.out.println(x + y + z);
}
}
只有类才存在静态的变量 方法只能对静态变量的操作 不能在方法内试图定义静态变量,否则的话会抛出编译错误。静态变量的本意是为了让所有的对象共享这个变量,如果在方法里面定义静态变量的话就存在逻辑错误了,也达不到你想要目的. 因为在方法中定义静态变量根本没有他的任何意义. 任何对象都有自己的方法,即使是静态方法,方法内的变量也是在方法调用时候才开始分配内存,所以想给成静态的在逻辑上存在问题
2、final、finally、finalize的区别
final:
在java,final可以用来修饰类,方法和变量。 修饰类:当final修饰类的时,表明该类不能被其他类所继承。注意final类中所有的成员方法都会隐式的定义为final方法。 修饰方法: 原因:(1)把方法锁定,以防止继承类对其进行修改。 (2)效率,在早期的java版本中,会将final方法转化位内嵌调用,当时由于方法过去庞大,可能在性能上不会有多大的提示,因此在最近版本中,不需要final方法进行这些优化了。 修饰变量: final成员变量表示常量,只能被赋值一次,赋值后其值不会改变。所以在final修饰成员变量(属性),必须要显示初始化。
finally:
1、finally作为异常处理的一部分,它用在try/catch语句中,并且附带一个语句块,表示这段语句最终一定会被执行(不管有没有抛出异常),经常被用在需要释放资源的情况下。(×)(这句话其实存在一定的问题) 2、只有与finally对应的try语句块得到执行的情况下,finally语句块才会执行。以上两种情况在执行try语句块之前已经返回或抛出异常,所以try对应的finally语句并没有执行。 3、因为我们在 try 语句块中执行了 System.exit (0) 语句,终止了 Java 虚拟机的运行。 4、因为finally用法特殊,所以会撤销之前的return语句,继续执行最后的finally块中的代码。
finalize:
finalize()是在java.lang.Object里定义的,也就是说,每一个对象都有这么个方法。这个方法在gc启动,该对象被回收的时候被调用。其实gc可以回收大部分的对象(凡是new出来的对象,gc都能搞定,一般情况下我们又不会用new以外的方式去创建对象),所以一般是不需要程序员去实现finalize的。 特殊情况下,需要程序员实现finalize,当对象被回收的时候释放一些资源,比如:一个socket链接,在对象初始化时创建,整个生命周期内有效,那么就需要实现finalize,关闭这个链接。 使用finalize还需要注意一个事,调用super.finalize();一个对象的finalize()方法只会被调用一次,而且finalize()被调用不意味着gc会立即回收该对象,所以有可能调用finalize()后,该对象又不需要被回收了,然后到了真正要被回收的时候,因为前面调用过一次,所以不会调用finalize(),产生问题。 所以,推荐不要使用finalize()方法,它跟析构函数不一样。
评论 null 条