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("子类有参构造执行了。");
}
}
/*
* 运行结果:
* 父类无参构造执行了。
* ------
* 父类无参构造执行了。
* 子类有参构造执行了。
* 子类无参构造执行了。
*/

浙公网安备 33010602011771号