Java类与对象

Java 类与对象

1. 成员变量与局部变量的区别

变量名 成员变量 局部变量
代码中位置 类中,方法外 方法中
存储中的位置 堆内存 栈内存
值变化 随对象变化,对象创建则存在,对象消失则消失 随方法变化,方法调用则存在,方法完成则回收
初始值 有初始值 没有初始值
同名时 采用“就近原则”,如果没有使用this关键字,则采取获取最近位置的变量的值

2. 静态关键字

  • (公共 / 构造)代码块

    每新建一个对象被调用一次。

  • 静态代码块

    存在于类中,当类被加载时,静态代码块会被执行,且只会执行一次。

    注释:因为_静态成员变量、方法、代码块都随类的加载而被调用_,优先于对象,因此静态方法中没有this对象。

示例代码:

构造代码块:对象每实例化一次,代码块执行一次

public class Student {
    private String name;
    private int age;
    
    public Student() {
        System.out.println("无参构造被执行了。");
    }
    
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("有参构造被执行了。");
    }
    
    {
        System.out.println("这是一个构造代码块。");
    }
}
class test {
    public static void main(String[] args) {
        Student s1 = new Student;
        Student s2 = new Student("小明", 12);
    }
}
/*
 * 运行结果:
 * 这是一个构造代码块。
 * 无参构造被执行了。
 * 这是一个构造代码块。
 * 有参构造被执行了。
 */

静态代码块:类被加载,代码块执行一次,且仅执行一次

public class Student {
    private String name;
    private int age;
    
    public Student() {
        System.out.println("无参构造被执行了。");
    }
    
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("有参构造被执行了。");
    }
    
    static {
        System.out.println("这是一个静态代码块。");
    }
}
class test {
    public static void main(String[] args) {
        Student s1 = new Student;
        Student s2 = new Student("小明", 12);
    }
}
/*
 * 运行结果:
 * 这是一个静态代码块。
 * 无参构造被执行了。
 * 有参构造被执行了。
 */

3. 判断代码执行的先后顺序

执行的先后顺序:

静态代码块 --- 构造代码块 --- 构造方法

/**
* Filename:    BlockOrderTest.java
* @version:    1.0
* @since:      JDK 1.6.0_21
* @author:	   lui
* Create at:   2019年6月22日
* Description: @测试代码块执行的先后顺序
* 
*/
package testCode;

class Student {
      
    public Student() {
         System.out.println("Student无参构造被执行了。");
      }
      
    {
        System.out.println("这是一个来自Student的构造代码块。");
    }
      
      static {
          System.out.println("这是一个来自Student的静态代码块。");
      }
  }

public class BlockOrderTest {
	

      public BlockOrderTest() {
          System.out.println("BlockOrderTest无参构造被执行了。");
      }
      
      {
          System.out.println("这是一个来自BlockOrderTest的构造代码块。");
      }
      
      static {
          System.out.println("这是一个来自BlockOrderTest的静态代码块。");
      }
      
      public static void main(String[] args) {
          Student s1 = new Student();
          BlockOrderTest t = new BlockOrderTest();
      }
	      
}
/*
 * 運行結果:
 * 这是一个来自BlockOrderTest的静态代码块。 
 * 这是一个来自Student的静态代码块。 
 * 这是一个来自Student的构造代码块。 
 * Student无参构造被执行了。
 * 这是一个来自BlockOrderTest的构造代码块。 
 * BlockOrderTest无参构造被执行了。
 */

4. 静态变量和实例变量的区别

静态变量属于类,该类不生产对象,通过类名就可以调用静态变量。
实例变量属于该类的对象,必须产生该类对象,才能调用实例变量。

在程序运行时的区别:
实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例
变量。
静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任
何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。

public class StaticTest {
    
	private static int staticInt = 0;
	private int random = 0;
	
	public  StaticTest() {
		staticInt++;	//	方法每调用一次+1
		random++;	// 对象调用一次+1,再调用不变
		System.out.println("staticInt=" + staticInt + " random=" + random);
	}
	@SuppressWarnings("unused")
	public static void main(String[] args) {
		StaticTest test1 = new StaticTest();
		StaticTest test2  = new StaticTest();
	}

}
/*
 * 运行结果: 
 * staticInt=1 random=1 
 * staticInt=2 random=1
 */

5. 不通过构造方法也能创建对象吗?

答:能。

Java创建对象的几种方式(重要):
(1) 用new语句创建对象,这是最常见的创建对象的方法。
(2) 运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。
(3) 调用对象的clone()方法。
(4) 运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法。
(1)和(2)都会明确的显式的调用构造函数 ;(3)是在内存上对已有对象的影印,所以不会调用构造函数 ;(4)是从文件中还原类的对象,也不会调用构造函数。

/**
* Filename:    BlockOrderTest.java
* @version:    1.0
* @since:      JDK 1.6.0_21
* @author:	   lui
* Create at:   2019年6月22日
* Description: @测试代码块执行的先后顺序
* 静态代码块 --- 构造代码块 --- 构造方法
*/
package testCode;

class Student {
      
//    public Student() {
//         System.out.println("Student无参构造被执行了。");
//      }
      
    {
        System.out.println("这是一个来自Student的构造代码块。");
    }
      
      static {
          System.out.println("这是一个来自Student的静态代码块。");
      }
  }

public class BlockOrderTest {
	
      public BlockOrderTest() {
          System.out.println("BlockOrderTest无参构造被执行了。");
      }
      
      {
          System.out.println("这是一个来自BlockOrderTest的构造代码块。");
      }
      
      static {
          System.out.println("这是一个来自BlockOrderTest的静态代码块。");
      }
      
      @SuppressWarnings("unused")
	public static void main(String[] args) {
          Student s1 = new Student();
          BlockOrderTest t = new BlockOrderTest();
      }
	      
}
/*
 * 運行結果:
 * 这是一个来自BlockOrderTest的静态代码块。 
 * 这是一个来自Student的静态代码块。 
 * 这是一个来自Student的构造代码块。 
 * 这是一个来自BlockOrderTest的构造代码块。 
 * BlockOrderTest无参构造被执行了。
 */

6. 继承中构造方法的执行顺序

  • 父类构造方法 —— 子类构造方法
  • 在有子父类继承关系的类中,创建子类的对象,调用子类的构造方法;
  • 如果子类构造方法(无参&有参)****的第一行代码没有调用父类的构造方法,则会默认**调用父类的无参构造;
  • 可以使用super()子类构造方法中的第一行调用父类的构造方法;
  • 肯定会有子类调用父类的构造方法,因为必须先对父类的对象初始化。

示例代码:

/**
* Filename:    ClassInheriteDemo.java
* @version:    1.0
* @since:      JDK 1.6.0_21
* @author:	   lui
* Create at:   2019年6月24日
* Description: @继承中构造方法的执行顺序
* 
*/
package testCode;

public class ClassInheriteDemo {

	public static void main(String[] args) {
		Father f = new Father();
		System.out.println("------");
		Son s = new Son();
	}

}

class Father {
	
	public Father() {	//	父类无参构造
		System.out.println("父类无参构造执行了。");
	}
	
	public Father(int age) {
		System.out.println("父类有参构造执行了。");
	}
	
}

class Son extends Father {
	
	public Son() {
		//super();	//	必须在子类无参构造方法的第一行调用super()方法执行父类的构造方法,且只能出现一次,注释不算。
		this(15);
		System.out.println("子类无参构造执行了。");
	}
	
	public Son(int age) {
        //	这里会默认调用父类的无参构造。
		System.out.println("子类有参构造执行了。");
	}
	
}

/*
 * 运行结果:
 * 父类无参构造执行了。
 * ------
 * 父类无参构造执行了。
 * 子类有参构造执行了。
 * 子类无参构造执行了。
 */
posted @ 2020-02-17 16:05  L7UI  阅读(181)  评论(0)    收藏  举报