Java的abstract,static ,final关键字的用法

关键概念:抽象类,抽象方法,静态类,静态内部类,静态方法,静态变量,常量,全局常量。

一、abstract的用法,修饰符,可以修饰类和方法 
1、abstract修饰类,会使这个类成为一个抽象类(详细的知识见java抽象类和抽象方法博文) 
  这个类将不能生成对象实例,但可以做为对象变量声明的类型,也就是编译时类型,
  抽象类就像当于一类的半成品,需要子类继承并覆盖其中的抽象方法。

2,abstract修饰方法,会使这个方法变成抽象方法,
  也就是只有声明(定义)而没有实现,实现部分以";"代替。需要子类继承实现(覆盖)。

3、 有抽象方法的类一定是抽象类。但是抽象类中不一定都是抽象方法,也可以全是具体方法。
abstract修饰符在修饰类时必须放在类名前。
abstract修饰方法就是要求其子类覆盖(实现)这个方法。调用时可以以多态方式调用子类覆盖(实现)后的方法,也就是说抽象方法必须在其

4、 子类中实现,除非子类本身也是抽象类。
父类是抽象类,其中有抽象方法,那么子类继承父类,并把父类中的所有抽象方法都实现(覆盖)了,子类才有创建对象的实例的能力,
否则子类也必须是抽象类。抽象类中可以有构造方法,是子类在构造子类对象时需要调用的父类(抽象类)的构造方法。

二、static 的用法,被修饰的方法称为静态方法,被修饰的变量称为静态变量(详细见静态变量和静态方法的博文)

关于静态变量和静态方法代码块,也就是JVM在加载静态变量和方法是会加载带内存中,作为公用的变量和方法,
也就是在对象创建之前就已经在内存中创建好对应的变量和方法。

1. 静态方法
 public static void prt(String s) {
       System.out.println(s);
    }
通常,在一个类中定义一个方法为static,那就是说,无需本类的对象即可调用此方法
   声明为static的方法有以下几条限制:
· 它们仅能调用其他的static 方法。
· 它们只能访问static数据。
· 它们不能以任何方式引用this 或super。

调用一个静态方法就是“类名.方法名”,静态方法的使用很简单如上所示。一般来说,静态方法常常为应用程序中的其它类提供一些
实用工具所用,在Java的类库中大量的静态方法正是出于此目的而定义的。
静态方法通常作为工具类或者工具方法中使用。

2、静态变量
 static int c = 0;
声明为static的变量实质上就是全局变量。当声明一个对象时,并不产生static变量的拷贝,而是该类所有的实例变量共用同一个static变量。
静态变量与静态方法类似。所有此类实例共享此静态变量,也就是说在类装载时,只分配一块存储空间,所有此类的对象都可以操控此块存储
空间,当然对于final则另当别论了。

静态方法代码块:一般可以作为一个对象的初始化的方法。
static{
  String driverClass="..";
  String url="";
  String username="";
  String password="";
}
以上代码就能初始化数据库连接

3、静态内部类,通常一个公用类不能设置为静态,只能是内部类设置为静态。
class OuterCls {
    public static class InnerCls {
       InnerCls() {
           System.out.println("InnerCls");
       }
    }
}
使用静态内部类:
public class StaticCls {
    public static void main(String[] args) {
       OuterCls.InnerCls oi = new OuterCls.InnerCls();
    }
}

4.static和final一块用表示什么
static final用来修饰成员变量和成员方法,可简单理解为“全局常量”!
对于变量,表示一旦给值就不可修改,并且通过类名可以访问。
对于方法,表示不可覆盖,并且可以通过类名直接访问。

5、补充总结说明: static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,
但是Java语言中没有全局变量的概念。

 被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。
只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,
无需引用任何对象。

 用public修饰的static成员变量和成员方法本质是全局变量和全局方法,当声明它类的对象时,不生成static变量的副本,
而是类的所有实例共享同一个static变量。

 static 变量前可以有private修饰,表示这个变量可以在类的静态代码块中,或者类的其他静态成员方法中使用(当然也可以在非静态成员
方法中使用--废话),但是不能在其他类中通过类名来直接引用,这一点很重要。实际上你需要搞明白,private是访问权限限定,
static表示不要实例化就可以使用,这样就容易理解多了。static前面加上其它访问权限关键字的效果也以此类推。

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

 用static修饰的代码块表示静态代码块,当Java虚拟机(JVM)加载类时,就会执行该代码块(用处非常大,呵呵)。

static变量
 按照是否静态的对类成员变量进行分类可分两种:一种是被static修饰的变量,叫静态变量或类变量;另一种是没有被static修饰的变量,
  叫实例变量。两者的区别是:
 对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,
  可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。
 对于实例变量,没创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。

static方法
 静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法中不能用this和super关键字,不能直接访问所属类的
实例变量和实例方法 (就是不带static的成员变量和成员成员方法),只能访问所属类的静态成员变量和成员方法。
因为实例成员与特定的对象关联!

因为static方法独立于任何实例,因此static方法必须被实现,而不能是抽象的abstract。

三、final关键字的使用

1. 修饰基础数据成员的一般称为常量,必须在声明的时候设置值。也成为编译时常数。
这是final的主要用途,其含义相当于C/C++的const,即该成员被修饰为常量,意味着不可修改。如java.lang.Math类中
的PI和E是final成员,其值为3.141592653589793和2.718281828459045。

2. 修饰类或对象的引用的final,一般使用的比较少。
在Java中,我们无法让对象被修饰为final,而只能修饰对象的引用,这意味着即使你写public final A a = new A();
 事实上a指向的对象的数据依然可以被修改,不能修改的是a本身的引用值,即你不能再对a进行重赋值。同样的情况出现
在数组中,比如public final int[] a = {1, 2, 3, 4, 5},事实上a中的数值是可修改的,即可以写
 a[0] = 3。据目前了解,java中数组内的数据是无法修饰为不可修改的,而C/C++可以。

3.修饰方法的类的子类只能使用不能修改或者叫重写。
  修饰方法的final和C/C++中修饰成员对象的const大不相同。首先,修饰方法的final含义不是“不可修改”,而是指该方法 
不可被继承成员重新定义。(注意,这里所说的不能被重新定义,并不是指子类一定不能定义同名方法,如果父类的方法是
私有类型,子类是允许定义该方法的,这里指的不能重新定义是指不能通过改写方法来使得方法重写的多态性得以实现,
如不希望A a = new B(); a.f();这样的重写方法情况出现)

此外,当一个方法被修饰为final方法时,意味着编译器可能将该方法用内联(inline)方式载入,所谓内联方式,是指编译器不用
像平常调用函数那样的方式来调用方法,而是直接将方法内的代码通过一定的修改后copy到原代码中(将方法主体直接插入到调用处,
而不是进行方法调用)。这样可以让代码执行的更快(因为省略了调用函数的开销),比如在int[] arr = new int[3]调用arr.length()等。
另一方面,私有方法也被编译器隐式修饰为final,这意味着private final void f()和private void f()并无区别。

4.修饰类的final的类不能被继承,例如String类。
当一个类被修饰为final时,它的含义很明确,就是不允许该类被继承,也就是说,该类“绝后”了,任何继承它的操作都会以
编译错误告终。这也凸显出Java用final而不用const作为标识符的理由。(成员变量可以不是final,成员方法直接是final的)

关于final还有比较深入的知识,这里不做太深入的了解。

五、Java语言的关键字synchronized用法,主要是在多线程中使用。
  当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。

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

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

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

4、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,
它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
5、以上规则对其它对象锁同样适用.

总结补充:
synchronized关键字的作用域有二种:
1)是某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法
(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能
同时访问这个对象中任何一个synchronized方法)。这时,不同的对象实例的synchronized方法是不相干扰的。
也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法;

2)是某个类的范围,synchronized static aStaticMethod{}防止多个线程同时访问这个类中的
synchronized static 方法。它可以对类的所有对象实例起作用。
2、除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中,表示只对这个区块
的资源实行互斥访问。用法是: synchronized(this){/*区块*/},它的作用域是当前对象;

3、synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是
synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法;
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值