MENU

this & static & 代码块

• November 14, 2020 • 面向对象编程

this & static & 代码块

this关键字

三个作用:

  1. 调用本对象成员属性
  2. 调用本对象成员方法
  3. 代表本实例对象

先从this调用属性说起

class Man{
    String name;
    int age;
    public Man(String n, int a) {        //参数与成员属性名称不一样
        name = n;
        age = a;
    }
    public void sing(){
        System.out.println("我会唱歌");
    }
    public void dance(){
        System.out.println("我会跳舞");
    }
}
public class Main {
    public static void main(String[] args) {
        Man man = new Man("小王", 18);
        System.out.println("姓名:"+man.name+" : "+"年龄:"+man.age);
    }
}

运行结果:

成功构造姓名为“小王”,年龄为18的一个男人
如果我们将构造方法的形式参数名改成和成员属性名一模一样

执行结果如下:

失败了!!!
为什么失败呢
因为构造方法里面的两条语句是没有意义的语句,就相当于1=1,2=2

为什么会这样?
因为代码块中,大括号{}中相同的变量名指的都是同一个对象,因此压根儿就没有成员属性的事儿,所以就没有初始化成功,姓名为null,年龄为默认的0

怎么样解决呢?
答案:this关键字 调用成员属性

我们将构造方法做以下修改:

利用this.来调用属性
运行结果正确!


this调用方法

  1. 调用构造方法 this();
  2. 调用普通方法 this.方法名();
调用构造方法

什么时候才会调用构造方法?
new 的时候
所以this.调用构造方法,只会出现在构造方法中
这里有一条铁律
如果要使用this调用构造方法,this();必须是第一条语句
构造方法互相调用时,一定要避免造成死循环(递归构造器调用)


static关键字

如果类的所有变量都具有同样的属性,那么这个属性就可以用static修饰
比如Person 这个类,每个人都有自己的国家,假如是中国民国,那么他们的所属国家都是一样的,而如今我们的国家改名为中华人民共和国,产品用户现有一亿人,我们就要对一亿人的国家属性进行修改,很明显一个一个改会让程序员疯掉的
那么 只要我们用static修饰国家这个属性,当修改一个对象的国家属性时,所有对象的国家属性都会变,因此可解决上述问题
代码如下:

class Person{
    private String name;
    private int age;
    static private String contry;
    
    public Person(String name, int age, String contry) {
        this.name = name;
        this.age = age;
        this.contry = contry;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getContry() {
        return contry;
    }
    public void setContry(String contry) {
        this.contry = contry;
    }
    public String getInfo(){
        return "姓名:"+this.getName()+"    年龄:"+this.getAge()+"      国家:"+this.getContry();
    }
}

public class Main {
    public static void main(String[] args) {
        Person person1 = new Person("代号001",20,"中华民国");
        Person person2 = new Person("代号002",21,"中华民国");
        Person person3 = new Person("代号003",22,"中华民国");
        System.out.println(person1.getInfo());
        System.out.println(person2.getInfo());
        System.out.println(person3.getInfo());
        System.out.println("修改第一个人的国家属性之后");
        person1.setContry("中华人民共和国");
        System.out.println("-----------------");
        System.out.println(person1.getInfo());
        System.out.println(person2.getInfo());
        System.out.println(person3.getInfo());
    }
}

运行结果:

所有人的国家都改变了
而我们如果不给contry用static修饰的话
运行结果是这样的:

只能修改一个人的国家,就很麻烦
所以static的方便性就显而易见了

这是内存分析

static修饰的属性存储在全局数据区内,所以一个对象更改,全部对象的都会跟着更改

上面的代码部分是不规范的
对于static修饰属性的访问,应该由权限最高者(类)来进行,而非单个对象,所以正确的更改国家的写法应该是:直接由类名称调用

由上面的代码做上图修改会遇到一个问题,contry是static的,但同时也被private修饰,那么在主方法中就不可能访问到contry这个变量,对此我们有两种解决方式:

  1. 取消对contry的private修饰
  2. 将setContry()方法用static修饰,主方法通过该方法来修改contry值

static 在类中定义,但是不受类实例化对象控制,也就是说,没有实例化对象的时候,static修饰的属性也可以直接使用
在进行设计开发的时候,首选非static属性,在考虑用到公共信息存储的时候才用到static属性。非static属性在实例化对象之后才能使用,而static属性不管有没有实例化对象,都可以直接使用

static修饰方法

在上面的第二个解决方式中就涉及到了用static修饰方法

  • static方法只能调用static属性或者static方法
  • 非static方法允许调用static属性或者static方法

原因很简单:static定义的属性和方法都可以在没有实例化对象的情况下使用,而非static定义的属性和方法不能在没有实例化对象的情况下使用


代码块

在程序中,使用的大括号{}括起来的结构就称为代码块
根据位置和定义的关键字不同,可分为普通代码块、构造块、静态块、同步代码块

普通代码块

在方法中被{}包围的代码,例如 for循环,if分支语句等等,都可以叫做一个代码块
在这些代码块中,{}还有一个作用?
在程序开发中,一个方法中是不允许出现同名变量的,但是,{}可以将方法进行结构拆分,以防止变量名相同
例如:

public class Main {
    public static void main(String[] args) {
        fun();
    }
    public static void fun(){
        for (int j = 0; j < 10; j++) {
            int i = 1;
            System.out.println("i = "+i+j);
        }
        int i = 10;
        System.out.println(i);
    }
}

从运行结果中我们可以知道,程序是没有报错,正常运行的

因为{}将方法结构划分了,在{}中代码执行完之后,自动将int i这个变量销毁,所以后续就没有i这个变量,因此可以在后面重新定义一个变量i

构造代码块

定义在类中,优先于构造方法执行,并且实例化新对象的时候都会执行一次

class Book{
    private String name;
    public Book(String name) {
        this.name = name;
        System.out.println("构造方法   执行");
    }
    {             //构造块
        System.out.println("构造块 执行");
    }
}
public class Main {
    public static void main(String[] args) {
        new Book("三国演义");
        new Book("西游记");
        new Book("红楼梦");
    }
}

运行结果:

结果:每一次都是代码块先执行,构造方法后执行

静态代码块

使用关键字static 定义的代码块
分为两种:主类中定义,非主类中定义

class Book{
    private String name;
    public Book(String name) {
        this.name = name;
        System.out.println("构造方法   执行");
    }
    static {
        System.out.println("静态代码块   执行");
    }
    {
        System.out.println("构造块   执行");
    }
}
public class Main {
    public static void main(String[] args) {
        new Book("三国演义");
        new Book("西游记");
        new Book("红楼梦");
    }
}

运行结果:

结果:静态代码块优先于构造块,构造方法执行,但是由始至终只会执行一次
主要作用是为类中的static属性初始化

探索

static静态代码块和主类中主方法的执行顺序

public class Main {
    static {
        System.out.println("静态代码块");
    }
    public static void main(String[] args) {
        System.out.println("主方法");
    }
}

答案:

静态代码块优先于主方法执行


代码编译器:IntelliJ IDEA 2020.02

Archives QR Code Tip
QR Code for this page
Tipping QR Code