this、super、final、static、synchronized 关键字可以修饰什么,以及修饰后的作用?

this关键字

this关键字主要分为四种情况

  1. 指的是当前对象本身

  2. 当你要把自己作为参数传递给别的对象时,也可以用this

  3. 有时候,我们会用到一些内部类和匿名类,如事件处理

        当在匿名类中用this时,这个this则指的是匿名类或内部类本身。
        这时如果我们要使用外部类的方法和变量的话,则应该加上外部类的类名。
    
  4. 在构造函数中,通过this可以调用同一类中别的构造函数

super关键字

有如下Java类:

public class Bird{   
private String name;   
public Bird() { }   
public Bird(String name){ this.name = name; }   
public void walk() { System.out.println(“走路”); }   
public String getName(){ return name; }   
public void setName(String name){ this.name = name; }   
}   

另有一个类Chicken继承上边的Bird类;

public class Chicken extends Bird{   
private String crest;   
public Chicken(){ super(); }   
public Chicken(String name,String crest) {   
super(name);   
this.name = name; }   
………….   
}   

在第二个自定义的类Chicken中,super()方法一共出现了两次,分别是super()和super(name),请问super() 是什么含义,放在这里又作何解释?

1.子类的构造过程中必须调用父类的构造方法。

2.子类可在自己的构造方法中使用super()来调用父类的构造方法。

(1)使用this来调用本类的另外的构造方法。

(2)如果调用super必须写在子类构造方法的第一行。

3.如果子类的构造方法中没有显示的调用父类的构造方法,则系统默认的调用父类的无参的构造方法。

4.如果子类的构造方法中既没有显示调用父类的构造方法,而父类中又没有无参的构造方法,则编译出错。

那你这里第 一个super()无参的就是调用了上面Bird类的Bird() 无参构造方法!

      super(name)这个有参数就是调用public Bird(String name){  this.name = name; }这个构造方法!

super() 是调用父类的构造函数,你例子中有Bird()和Bird(String name)两个方法,super()是调用Bird()构造函数,而super(name)是调用Birth(String name)构造函数。注意super() 调用的是对应参数个数和类型相同的父类构造函数。 public Chicken(String name,String crest) { super(name); this.name = name; } 应该重复了吧,super(name)应该就是this.name = name。

final关键字

  1. final数据
    对于基本数据类型的数据而言,final修饰符表示,该数据不会被修改。
    对于非基本类型的对象引用而言,final修饰符所限定的引用恒定不变。一旦引用被初始化指向一个对象,就无法对其改变以指向另一个对象(然而,对象自身却是可以被修改的。Java并未提供任何使“对象”恒定不变的途径。这一限制同样适用于数组,它也是对象)。
    在这里插入图片描述

  2. final方法—不能被重载
    使用final方法的原因有两个。第一个原因是把方法锁定,以预防任何继承类修改它的意义。这是出于设计的考虑:你想要确保在继承中方法的行为不变,并且不会被重写。
    注:类中的private方法隐含为final方法,它不可被重写。因此,在private方法前加上final修饰符是没有意义的。

  3. final类–不能被继承,final类中的方法默认为final
    如果某个类整体被定义为final,则该类不可被继承,它不可有子类。这种设计可能是出于安全或其他方面的考虑。
    final类中的所有方法都隐含为final类型的,因为final类本身是不可被继承的,所以类中的方法也不能被重写(override)。在final类中,你可以给方法添加final修饰符,但这不会增加任何意义
    使用final方法的第二个原因是效率。如果你将一个方法指明为final,就是同意编译器将针对该方法的所有调用都转为内嵌(inline)调用。当编译器发现一个final方法调用命令时,它会根据自己的谨慎判断,跳过插入程序代码的正常方式而执行方法调用机制(将参数压入栈中,跳至方法代码处并执行,然后跳回去并清除栈中的参数,处理返回值),并且以方法体中的实际代码的复本来替代方法调用。这将消除方法调用的开销。当然,如果一个方法很大,你的程序代码就会膨胀,你可能看不到内嵌带来的任何性能提高。因此,你所取得的性能提高会因为花费于方法内时间总量而被缩减。这意味着Java编译器能够观察到这些情况并明智的抉择是否对final方法执行内嵌动作。然而,最好是让编译器和JVM仅在你明确表示要阻止重写(override)时,再考虑效率问题,并将方法指明为final。

    Java中除了static和final方法(private方法属于final)外,其他所有的方法都是后期绑定(动态绑定)。因此,将方法声明为final,可以有效的“关闭”动态绑定,或者是想告诉编译器,不需要对其进行动态绑定。这样,编译器就可以为final方法调用生成更有效的代码。然而,大多数情况下,这样做对程序的整体性能不会产生什么改观。

static关键字(静态方法–静态变量–静态块–静态内部类)

static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,更可以修饰类级内部类,但是Java语言中没有全局变量的概念。 被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享 。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们 。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。
用public修饰的static成员变量和成员方法本质是全局变量和全局方法,当声明它类的对象时,不生成static变量的副本,而是类的所有实例共享同一个static变量。 static变量前可以有private修饰,表示这个变量可以在类的静态代码块中,或者类的其他静态成员方法中使用(当然也可以在非静态成员方法中使用–废话),但是不能在其他类中通过类名来直接引用,这一点很重要。实际上你需要搞明白,private是访问权限限定,static表示不要实例化就可以使用,这样就容易理解多了。static前面加上其它访问权限关键字的效果也以此类推。

static修饰的成员变量和成员方法习惯上称为静态变量和静态方法,可以直接通过类名来访问,访问语法为:

类名.静态方法名(参数列表…)
类名.静态变量名
用static修饰的代码块表示静态代码块,当Java虚拟机(JVM)加载类时,就会执行该代码块(用处非常大,呵呵)。
1、static变量
按照是否静态的对类成员变量进行分类可分两种:一种是被static修饰的变量,叫静态变量或类变量;另一种是没有被static修饰的变量,叫实例变量。两者的区别是:
对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。
对于实例变量,没创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。
2、静态方法
静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法中不能用this和super关键字,不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员成员方法),只能访问所属类的静态成员变量和成员方法。因为实例成员与特定的对象关联!这个需要去理解,想明白其中的道理,不是记忆!!!
因为static方法独立于任何实例,因此static方法必须被实现,而不能是抽象的abstract。
3、static代码块
static代码块也叫静态代码块,是在类中独立于类成员的static语句块,可以有多个,位置可以随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次。

4、类加载
JVM在第一次使用一个类时,会到classpath所指定的路径里去找这个类所对应的字节码文件,并读进JVM保存起来,这个过程称之为类加载。
可见,无论是变量,方法,还是代码块,只要用static修饰,就是在类被加载时就已经"准备好了",也就是可以被使用或者已经被执行。都可以脱离对象而执行。反之,如果没有static,则必须通过对象来访问。

注意
声明为static的变量实质上就是全局变量。当声明一个对象时,并不产生static变量的拷贝,而是该类所有的实例变量共用同一个static变量,例如:声明一个static的变量count作为new一个类实例的计数。

声明为static的方法有以下几条限制:

它们仅能调用其他的static 方法。
它们只能访问static数据。
它们不能以任何方式引用this 或super。
static方法与覆盖
静态方法只能被隐藏,不能被覆盖,隐藏表明还存在,还会起作用–子类隐藏父类的静态方法,仍会执行父类的静态方法.

synchronized关键字

  1. 简单介绍

synchronized 是java语言关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块。

  1. 可以修饰哪些内容

一、 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;

二、修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;

三、修饰一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;

四、修饰一个类,其作用的范围是synchronized后面括号括起来的部分,作用的对象是这个类的所有对象。

  1. synchonized(this)和synchonized(object)区别

其实并没有很大的区别,synchonized(object)本身就包含synchonized(this)这种情况,使用的场景都是对一个代码块进行加锁,效率比直接在方法名上加synchonized高一些(下面分析),唯一的区别就是对象的不同。

对synchronized(this)的一些理解

一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

四、当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

4.sychonized method 和 synchonized代码块的效率问题

使用前者的对象会获取该对象中所有synchonized的锁,也就是其他线程不能访问所有加了synchonized前缀的方法(不仅仅只是当前运行的方法),影响了其他线程同步方法的访问,降低了效率。而后者只对当前代码块加锁,其他的同步方法不受影响。

  1. 结论

1.synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。

2.synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。

3.在static方法前加synchronized:静态方法属于类方法,它属于这个类,获取到的锁,是属于类的锁。

4.在普通方法前加synchronized:非static方法获取到的锁,是属于当前对象的锁。

5.类锁和对象锁不同,synchronized修饰不加static的方法,锁是加在单个对象上,不同的对象没有竞争关系;修饰加了static的方法,锁是加载类上,这个类所有的对象竞争一把锁。

参考地址

https://juejin.im/post/5c3c5e0ce51d4551d04511c9
https://blog.csdn.net/wenbingoon/article/details/8887708

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值