(1)一个人只要自己不放弃自己,整个世界也不会放弃你.
(2)天生我才必有大用
(3)不能忍受学习之苦就一定要忍受生活之苦,这是多么痛苦而深刻的领悟.
(4)做难事必有所得
(5)精神乃真正的刀锋
(6)战胜对手有两次,第一次在内心中.
(7)编写实属不易,若喜欢或者对你有帮助记得点赞+关注或者收藏哦~
Java SE 024 static与final使用陷阱 续
文章目录
1.final成员变量赋初值
public class FinalTest4{
final int a;
}
(1)对于一个一般的成员变量来说,如果我们没有给它赋初值,那么它的默认值就取0;
(2)但是对于一个final类型的变量来说,我们必须要显示的给它赋初值。
(3)因为对于普通的成员变量来说,如果我们不给它赋初值,我们后面还有机会给它赋
(4)对于final类型,如果不给它赋初值,就没有机会在后面赋值了。所以必须显示的赋初值。
1.1常量赋初值
public class FinalTest4{
final int a=0;
}
1.2可以通过构造方法显示的赋初值
public class FinalTest4{
final int a;
public FinalTest4(){
a = 0;
}
}
1.3 两个构造方法 编译通不过
public class FinalTest4{
final int a;
public FinalTest4(){
a = 0;
}
public FinalTest4(int a){
}
}
(1)当我构造对象的时候,到底是使用第一个构造方法,还是使用第二个构造方法,是由我来指定的,如果使用第一个构造方法,没问题,它已经被赋上初值,如果使用第二个构造方法,a没有赋上初值,因此就会提示“可能尚未初始化变量a”
1.4小结:
(1)对于final类型的成员变量来说,它的赋值方式有两种,第一种是在声明的时候直接给它赋上值。
(2)第二种方式是在声明的时候不给它赋值,并且在这个类的所有的构造方法里面都要给个成员变量赋上初值。
public class FinalTest4{
final int a;
public FinalTest4(){
a = 0;
}
public FinalTest4(int a){
this.a = a;//都会给a赋上值。
}
}
1.5对于final类型成员变量,一般来说有两种赋初值方式
(1)在声明final类型的成员变量时就赋上初值。
(2)在声明final类型的成员变量时不赋上值,但在类的所有构造方法中都为其赋上初值。
2.static静态代码块
public class StaticTest4{
public static void main(String [] args){
P p = new P();
}
}
class P{
static {
System.out.println("static block");
}
public P(){
System.out.println("P constructor");
}
}
解说:
(1)静态代码块是先于构造方法执行的
-
这个为什么会存在这种情况呢,因为静态代码块的执行时机是,当你定义好一个类之后,这个类会生成一个Class文件放在硬盘上,然后当我们执行的时候,会先加载到java虚拟机上,接着由java虚拟机再去处理它,由它去生成对象。
-
当从硬盘将class文件加载到java虚拟机上的时候,这个static代码块就已经去执行了
-
而构造方法是什么时候执行呢?
是在生成对象的时候才去执行的。刚把class文件加载到java虚拟机上,这个时候还没生成对象,所以构造方法后执行。因为它是要生成对象的时候,它才会执行。
- 而静态代码块加载的时候就会去执行。
public class StaticTest4{
public static void main(String [] args){
P p = new P();
P p2 = new P();
}
}
class P{
static {
System.out.println("static block");
}
public P(){
System.out.println("P constructor");
}
}
执行结果:
(1)两个P contructor好理解,因为生成了两个对象,而静态代码块儿中的代码为什么只出现一次呢?
因为类加载的时候只需要加载一次就够了。
public class StaticTest4{
public static void main(String [] args){
new S();
}
}
class P{
static {
System.out.println("static block");
}
public P(){
System.out.println("P constructor");
}
}
class Q extends P{
static {
System.out.println("Q static block");
}
public Q(){
System.out.println("Q Contructor");
}
}
class S extends Q{
static {
System.out.println("S static block");
}
public S(){
System.out.println("S constructor");
}
}
执行结果:
先是最上层的静态代码块,即在类进行加载的时候,会先去找父类的静态代码块,父类的有了再去找子类的代码块,依次循环下去。
2.1.小结
(1)静态代码块也是完成一些初始化工作。
- 首先执行静态代码块,然后执行构造方法。
- 静态代码块在类被加载的时候执行,而构造方法是在生成对象的时候执行.
- 要想调用某个类来生成对象,首先需要将类加载到java虚拟机上(JVM),然后由JVM加载这个类来生成对象。
(2)类的静态代码块只会执行一次
- 是在类被加载的时候执行的,因为每个类只会加载一次,所以静态代码块也只会被执行一次;
- 而构造方法则不然,每次生成一个对象的时候都会调用类的构造方法,所以new一次就会调用构造方法一次。
(3)如果继承体系中既有构造方法,又有静态代码块,那么首先执行最顶层的类的静态代码块,一直执行到最底层类的静态代码块,然后再去执行最顶层类的构造方法,一直执行到最底层类的构造方法。
注意静态代码块只会执行一次。
3.静态方法访问非静态成员变量
3.1不能在静态方法里面访问非静态的成员变量。
public class StaticTest5{
public static void main(String [] args){
W.change();
}
}
class W{
int a = 10;
public static void change(){
a++;
}
}
3.1.1为什么不能访问:
(1)change()方法是一个静态方法,可以通过类的名字去调用,没有使用任何一个对象的引用去调用。
(2)假如说当前代码是可以的,可以在静态方法里面访问非静态的成员变量,那么一调用change()方法,就将a变成++了。
(3)a是一个非静态的成员变量,每一个对象都会有一个a,那么a++改的是哪一个对象上的a呢?
找到一个理由就能证明这个是矛盾的,是ok的。
(4)所以不能在静态的方法里面去访问非静态的成员变量。
3.2.静态方法可以访问静态的成员变量
public class StaticTest5{
public static void main(String [] args){
W.change();
}
}
class W{
static int a = 10;
public static void change(){
a++;
}
}
为什么可以访问?
因为静态成员变量只有一个,即便是通过类来改,改的还是那一个,不管哪一个对象引用都是引用的那一个,这是没问题的。所以静态的方法可以改变静态的成员变量。
public class StaticTest5{
public static void main(String [] args){
W w = new W();
w.change();
}
}
class W{
static int a = 10;
public void change(){
a++;
}
}
此段代码执行成功:为什么?
因为虽然change()是一个非静态的方法,要通过对象去调用,不管通过哪个对象,改的还是唯一的一份儿。
3.3小结
(1)静态的访问静态的,非静态的什么都可以访问。
- 不能在静态方法中访问非静态成员变量。
- 可以在静态方法中访问静态的成员变量。
- 可以在非静态的方法中访问静态的成员变量。
public class StaticTest5{
public static void main(String [] args){
W w = new W();
w.change();
}
}
class W{
static int a = 10;
public static void change(){
this.a++;
}
}
(1)this也是一个非静态的变量。
(2)this表示对当前对象的一个引用,换句话说一定要有一个对象,如果我直接调用这个方法的时候,我可以通过类来去调用,没有对象,那么this是谁呢?判断不出来,所以以上代码也不对。
StaticTest5{
public static void main(String [] args){
W w = new W();
w.change();
}
}
class W{
static int a = 10;
public static void change(){
this.a++;
}
}
(1)this也是一个非静态的变量。
(2)this表示对当前对象的一个引用,换句话说一定要有一个对象,如果我直接调用这个方法的时候,我可以通过类来去调用,没有对象,那么this是谁呢?判断不出来,所以以上代码也不对。
(3)不能在静态方法中使用this关键字。