Java对象学习

1、实例变量与类变量的比较

(1)、在类中定义的变量成为成员变量,对于带static关键字的变量成为类变量或静态变量,反之成为实例变量或非静态变量

(2)、在类中定义的变量成为成员变量,对于带static关键字的变量成为类变量或静态变量,反之成为实例变量或非静态变量。

(3)、类变量属于类本身,伴随着类本身的初始化而完成内存分配,无论该类new了多少个实例,改变只有一个。类变量的初始化总是在实例变量的前面。

(4)、实例变量就是在new一个对象的时候才初始化,分配内存空间

(5)、static关键字可以修饰在类中定义的成员,包括成员变量、方法、内部类、初始化块、内部枚举;不能修饰外部类、局部变量、局部内部类。

创建一个人员类:

public class Person {

    private String name;
    private int age;
    public static int money;

    public void display() {
        System.out.println("姓名:" + getName() + ";年龄:" + getAge());
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return the age
     */
    public int getAge() {
        return age;
    }

    /**
     * @param age the age to set
     */
    public void setAge(int age) {
        this.age = age;
    }
}
 public static void main(String[] args) {
        System.out.println("Person的类变量money初始值:" + Person.money);
        Person.money = 10;
        System.out.println("Person的类变量money:" + Person.money);

        Person p1 = new Person();
        p1.setName("张三");
        p1.setAge(21);
        p1.money = 20;//这样用也可以、但是建议用Person.money = 10;
        p1.display();
        System.out.println("Person的类变量money:" + Person.money);
        
        Person p2 = new Person();
        p2.display();
    }

结果为:

Person的类变量money初始值:0
Person的类变量money:10
姓名:张三;年龄:21
Person的类变量money:20
姓名:null;年龄:0

money为static变量,只创建一次,这里设置为public,其他的实例都可以直接访问它,并且访问的还是同一个。最好将其设置为private,不给其他实例直接访问,只能通过类本身来访问

2、实例变量初始化先后顺序

(1)、定义实例变量时指定初始值

(2)、非静态初始化块对实例变量赋值

构造方法赋值

public class Cat {

    private String name;
    private int age;

     public Cat(String name, int age,double weight) {
        this.name = name;
        this.age = age;
        this.weight=weight;
    }
    {
        System.out.println("执行非静态初始化块——重量:" + getWeight());
        System.out.println("执行非静态初始化块");
        setWeight(22.2);
        System.out.println("执行非静态初始化块——重量:" + getWeight());
    }
    private double weight = 12.3;

    static {
        System.out.println("执行静态初始化块");
    }

    public void display() {
        System.out.println("名称:" + getName() + ";年龄:" + getAge() + ";重量:" + getWeight());
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return the age
     */
    public int getAge() {
        return age;
    }

    /**
     * @param age the age to set
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * @return the weight
     */
    public double getWeight() {
        return weight;
    }

    /**
     * @param weight the weight to set
     */
    public void setWeight(double weight) {
        this.weight = weight;
    }
}
 public static void main(String[] args) {
        Cat c1 = new Cat("测试1", 10,10.1);
        c1.display();
        Cat c2 = new Cat("测试2", 20,20.1);
        c2.display();
    }

结果为:

执行静态初始化块
执行非静态初始化块——重量:0.0
执行非静态初始化块
执行非静态初始化块——重量:22.2
名称:测试1;年龄:10;重量:10.1
执行非静态初始化块——重量:0.0
执行非静态初始化块
执行非静态初始化块——重量:22.2
名称:测试2;年龄:20;重量:20.1

从上面可以看出,静态初始化块总是执行在前面,且每new一个对象就执行一次,构造方法赋值总是在最后面;

这里并没有输出weight=12.3而是输出为0.0说明非静态初始化块执行顺序在定义变量时赋值的前面,然后并非如此,交换非静态初始化块与weight定义时赋值赋值语句的先后顺序者的顺序

结果为:

执行静态初始化块
执行非静态初始化块——重量:12.3
执行非静态初始化块
执行非静态初始化块——重量:22.2
名称:测试1;年龄:10;重量:10.1
执行非静态初始化块——重量:12.3
执行非静态初始化块
执行非静态初始化块——重量:22.2
名称:测试2;年龄:20;重量:20.1

得出结论:静态初始化块最早,构造方法最晚,非静态初始化块与定义实例变量赋值的语句按先后顺序来判断
3、类变量初始化先后顺序

(1)、定义类变量时指定初始值

(2)、静态初始化块指定初始值

public class Test {

    static int count = 1;

    static {
        count = 2;
    }

    static {
        name = "测试2";
    }
    static String name = "测试1";

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        System.out.println("count值:" + Test.count);
        System.out.println("name值:" + Test.name);
    }

得出结论:

这两种方式执行顺序与他们在代码中的先后顺序一致

4、构造方法执行先后顺序

当用构造方法创建一个类的实例的时候,首先执行父类的非静态初始化块、构造方法,然后再执行本类的非静态初始化块、构造方法

(1)、执行Object类非静态非静态初始化块(没有就不执行)
(2)、执行Object类的构造方法(有时候是隐式调用的)

(3)、执行父类的非静态初始化块(没有就不执行)

(4)、执行父类的构造方法(有时候是隐式调用)

(5)、执行本类非静态初始化块(没有就不执行)

(6)、执行本类的构造方法

public class Son extends Parent {

    static {
        System.out.println("儿子的静态初始化块");
    }

    {
        System.out.println("儿子的非静态初始化块");
    }

    public Son() {
        super("张三", 25);
        System.out.println("儿子无参构造方法");
    }

    public Son(String name) {
        this();
        System.out.println("儿子有参构造方法" + name);
    }
}

class Parent extends GrandFather {

    static {
        System.out.println("父亲的静态初始化块");
    }

    {
        System.out.println("父亲的非静态初始化块");
    }

    public Parent(String parent) {
        super(parent);
        System.out.println("父亲一个参数构造方法" + parent);
    }

    public Parent(String name, int age) {
        this(name);
        System.out.println("父亲两个参数构造方法" + name);
    }
}

class GrandFather {

    static {
        System.out.println("爷爷的静态初始化块");
    }

    {
        System.out.println("爷爷的非静态初始化块");
    }

    public GrandFather() {
        System.out.println("爷爷无参构造方法");
    }

    public GrandFather(String name) {
        this();
        System.out.println("爷爷有参构造方法" + name);
    }
}
public class Test {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Son s = new Son("三毛");
    }
}

结果为:

爷爷的静态初始化块
父亲的静态初始化块
儿子的静态初始化块
爷爷的非静态初始化块
爷爷无参构造方法
爷爷有参构造方法张三
父亲的非静态初始化块
父亲一个参数构造方法张三
父亲两个参数构造方法张三
儿子的非静态初始化块
儿子无参构造方法
儿子有参构造方法三毛

结论:可以看出

(1)、首先是加载静态的资源,然后再是非静态初始化块,然后再是构造方法

(2)、系统总是从最顶层的父类开始初始化操作

5、访问子类对象的实例变量

continue………………

 


 




 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值