以上就是给各位分享java--static/final/abstract,同时本文还将给你拓展4.11abstract类和abstract方法、5-2Java中的static使用之静态变量;;Java
以上就是给各位分享java -- static/final/abstract,同时本文还将给你拓展4.11 abstract 类和 abstract 方法、5-2 Java 中的 static 使用之静态变量 ;;Java 中的 static 使用之静态方法;;Java 中的 static 使用之静态初始化块、Abstract vals && Abstract vars、abstract 类和 abstract 方法等相关知识,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
本文目录一览:- java -- static/final/abstract
- 4.11 abstract 类和 abstract 方法
- 5-2 Java 中的 static 使用之静态变量 ;;Java 中的 static 使用之静态方法;;Java 中的 static 使用之静态初始化块
- Abstract vals && Abstract vars
- abstract 类和 abstract 方法
java -- static/final/abstract
#1.static
当一个方法或者变量需要初始化时被加载,或者是经常被调用的时候,可以使用 static 修饰它们。 弊处是:初始化被加载,比较占用内存。
java 语言中没有 全局变量 这个概念,可以使用 static 表示 "全局变量 (或方法)",因为被 static 修饰的变量 / 方法不依赖于任何类的实例,它被所有类的实例共享。
static 修饰符可以与 变量、方法、类 (内部类) 一起使用,表示 "静态" 的。
静态变量 / 方法通过 类名 来访问,因此它们也被称作类变量 / 类方法。
实例变量 / 方法需要通过类的实例来访问。
##1. 静态变量 静态变量属于类,不是对象,因此无需创建类的实例就可以访问它。编译器只会给静态变量分配一个内存空间,虽然会有多个实例 (类每调用一次),但这些实例共享该内存。实例变量则不同,每创建一个对象,都会被分配一次内存空间,不同实例之间的内存相互独立,互不影响,改变 a 的实例变量不会影响 b 的实例变量。
static 修饰的变量在类加载的时候就会被初始化,也就是说,只要类被加载,不管是否用了这个 static 变量,它都会被初始化。以后在生成类的实例 (类名。变量) 时,将共享这个变量,任何一个对象修改 静态变量,都会影响其他类对它的使用。
静态变量与实例变量的区别
1. 静态变量需要被 static 修饰,实例变量不需要。
2. 静态变量只会被加载一次,即只分配一次内存,可以用类名直接访问,所有的类都可以操作静态变量,因此静态变量的值可能会被各个类修改,即所有的类共享该变量;对于属性变量,没创建一个实例,都会为该实例的属性分配一次内存,因此各个实例的属性之间互不影响,即修改了实例 A 的 cc 属性不会影响实例 B 的 cc 属性 (备注:实例 A 与实例 B 同属于一个类)。
3. 静态变量使用场景
1 > 各个对象之间共享该变量 (多线程)
2 > 经常需要访问该变量
##2. 静态方法
1. 静态方法同静态变量一样,也是被各个类的实例共享。因此,静态方法中不能出现 this 与 super 关键字。
2. 静态方法不能操作它所属类的非静态变量。
静态方法使用场景:
1. 一个方法不需要操作对象,其所需参数都是显式参数提供 (例如:Math.pow ())。
2. 一个方法只需要访问类的静态变量。
static 和 final 组合使用
static 与 final 组合修饰的变量 / 方法 / 类,可以理解为 "全局常量 / 方法 / 类"。
很明显,static 修饰的变量可以被所有类的实例使用,因此表示 "全局";final 修饰的变量值不可以被改变,因此表示 "常量"。
static final 变量:表示该变量一旦给定值,就不可以修改。
static final 方法:表示该方法不可以被覆盖,即不能被重写。
static final 类:该类是一个内部类,该类不能被继承。
#2.final
final 可以修饰类、方法、变量。表示 “最终” 的意思。
1.final 修饰的类不能被继承
2.final 修饰的方法不能被子类重写
3.final 修饰的变量,即为常量,只能被赋值一次
#3.abstract
抽象修饰符,它可以修饰类和方法。
abstract 修饰类:使这个类变成一个抽象类,即这个类不能实例化对象。它需要被子类继承,并实现其方法。
abstract 修饰方法:使这个方法变成抽象方法,即该方法只有声明没有实现,需要在子类中实现。
备注:
1. 存在抽象方法的类一定是抽象类;反过来,抽象类中不一定全部都是抽象方法,它可以有实现的方法。
2. 子类继承抽象类后,如果需要实例化对象,则该子类必须要实现父类所有的方法;否则,该子类也必须是抽象类 (即子类如果没有完全覆写抽象父类的方法,盖子类也必须是抽象类;只有完全覆写了,该子类才可以实例化对象)。
4.11 abstract 类和 abstract 方法
abstract class A
{ …
}
abstract class A{
abstract int min(int x,int y);
int max(int x,int y){
return x>y?x:y;
}
}
class B extends A{
int min(int x,int y){
return x<y?x:y;
}
}
public class AbstractExample{
public static void main(String args[]){
A a;
//a=new A();非法,抽象类不能实例化
B b = new B();
int max = b.max(11,22);
int min = b.min(11,22);
System.out.println("max="+max+" min="+min);
a = b;
max = a.max(11,22);
System.out.println("max="+max);
}
}
5-2 Java 中的 static 使用之静态变量 ;;Java 中的 static 使用之静态方法;;Java 中的 static 使用之静态初始化块
1.Java 中被 static 修饰的成员称为静态成员或类成员。它属于整个类所有,而不是某个对象所有,即被类的所有对象所共享。静态成员可以使用类名直接访问,也可以使用对象名进行访问。当然,鉴于他作用的特殊性更推荐用类名访问
使用 static 可以修饰变量、方法和代码块。
2. 与静态变量一样,我们也可以使用 static 修饰方法,称为静态方法或类方法。其实之前我们一直写的 main 方法就是静态方法。静态方法的使用如:
注意:
1、 静态方法中可以直接调用同类中的静态成员,但不能直接调用非静态成员。如:
如果希望在静态方法中调用非静态变量,可以通过创建类的对象,然后通过对象来访问非静态变量。如:
2、 在普通成员方法中,则可以直接访问同类的非静态变量和静态变量,如下所示:
3、 静态方法中不能直接调用非静态方法,需要通过对象来访问非静态方法。如:
3.Java 中的 static 使用之静态初始化块
Java 中可以通过初始化块进行数据赋值。如:
在类的声明中,可以包含多个初始化块,当创建类的实例时,就会依次执行这些代码块。如果使用 static 修饰初始化块,就称为静态初始化块。
注意:静态初始化块只在类加载时执行,且只会执行一次,同时静态初始化块只能给静态变量赋值,不能初始化普通的成员变量。
Abstract vals && Abstract vars
Abstract vals && Abstract vars
在 scala 中抽象类和特质都可以定义抽象的成员变量。
Abstract vals && Abstract vars
abstract class Abstract {
type T
def transform(x: T): T
val initial: T
var current: T
}
class Concrete extends Abstract {
override type T = String
override def transform(x: T): T = x + x
//在Java里这是final变量,所以必须要初始化赋值
override val initial: T = "string"
//在Java里这个private类型变量,在scala中可以yoga下划线赋值
override var current: T = _
}
object Main9 {
def main(args: Array[String]): Unit = {
val c = new Concrete
println(c.initial) //string
println(c.current) //null
}
}
如上的示例,定义两个抽象的成员变量,
val initial: T
var current: T
同时实现类实现抽象类的时候必须要赋值重写。在 Java 里看起来很怪,那么在 Java 里是如何实现的呢,通过 javap 反编译看一下
C:\WorkSpace5-gitosc\scala-sample\out\production\scala-sample\com\usoft3>javap -p Abstract.class
Compiled from "test.scala"
public abstract class com.usoft3.Abstract {
public abstract java.lang.Object transform(java.lang.Object);
public abstract java.lang.Object initial();
public abstract java.lang.Object current();
public abstract void current_$eq(java.lang.Object);
public com.usoft3.Abstract();
}
C:\WorkSpace5-gitosc\scala-sample\out\production\scala-sample\com\usoft3>javap -p Concrete.class
Compiled from "test.scala"
public class com.usoft3.Concrete extends com.usoft3.Abstract {
private final java.lang.String initial;
private java.lang.String current;
public java.lang.String transform(java.lang.String);
public java.lang.String initial();
public java.lang.String current();
public void current_$eq(java.lang.String);
public void current_$eq(java.lang.Object);
public java.lang.Object current();
public java.lang.Object initial();
public java.lang.Object transform(java.lang.Object);
public com.usoft3.Concrete();
}
其实在 scala 中定义的抽象字段在反编译后的 java 类中,其实就是抽象方法,
public abstract java.lang.Object initial();
public abstract java.lang.Object current();
那么也就不难理解了。
Initializing abstract vals
如下定义的抽象类中含有两个抽象变量
abstract class Abstract {
val numerArg: Int
val denomArg: Int
}
javap 反编译 Abstract 抽象类
C:\WorkSpace5-gitosc\scala-sample\out\production\scala-sample\com\usoft4>javap -p Abstract.class
Compiled from "test.scala"
public abstract class com.usoft4.Abstract {
public abstract int numerArg();
public abstract int denomArg();
public com.usoft4.Abstract();
}
scala 中实现抽象类的方式最简单的如下,同时也必须重写抽象变量
new Abstract {
override val denomArg: Int = 1
override val numerArg: Int = 2
}
我们打印一下这个实现类的 className
println(new Abstract {
override val denomArg: Int = 1
override val numerArg: Int = 2
}.getClass.getName)
com.usoft4.Main9$$anon$1,javap 反编译
C:\WorkSpace5-gitosc\scala-sample\out\production\scala-sample\com\usoft4>javap -p Main9$$anon$1.class
Compiled from "test.scala"
public final class com.usoft4.Main9$$anon$1 extends com.usoft4.Abstract {
private final int denomArg;
private final int numerArg;
public int denomArg();
public int numerArg();
public com.usoft4.Main9$$anon$1();
}
反编译的 Abstract 抽象类中是没有定义的成员变量的,只是在抽象类的实现类中出现了父类的成员变量。
这其实就是 Java 中的匿名类的概念。
=================END=================
abstract 类和 abstract 方法
可以使用 abstract 来修饰一个类或者方法。
用 abstract 修饰的类表示这个类是一个抽象类,用 abstract 修饰的方法表示这个方法是一个抽象方法。
抽象类不能被实例化。
抽象方法是只有方法声明,而没有方法的实现内容。
abstract 抽象类
可以使用 abstract 来修饰一个类。
用 abstract 修饰的类表示这个类是一个抽象类。
抽象类不能被实例化。
这是一个简单抽象的方法,如果它被直接实例化,系统会报错。
<?php
//定义一个抽象类
abstract class User
{
public function __toString() {
return get_class($this);
}
}
//实例化这个类会出现错误
echo new User();
?>
下面例子的 NormalUser 继承自 User 类,就可以被实例化了。
<?php
//定义一个抽象类
abstract class User
{
public function __toString() {
return get_class($this);
}
}
//实例化这个类会出现错误
echo new User();
class NormalUser extends User
{
}
$a = new NormalUser();
echo "这个类" . $a . "的实例";
?>
单独设置一个抽象类是没有意义的,只有有了抽象方法,抽象类才有了血肉。下面介绍抽象方法。
abstract 抽象方法
用 abstract 修饰的类表示这个方法是一个抽象方法。
抽象方法,只有方法的声明部分,没有方法体。
抽象方法没有 {} ,而采用;结束。
一个类中,只要有一个抽象方法,这个类必须被声明为抽象类。
抽象方法在子类中必须被重写。
下面是一个抽象类,其中有两个抽象方法,分别是 setSal () 和 getSal ()。用来取回 $sal 员工的工资。
<?php
abstract class User
{
protected $sal = 0;
//这里定义的抽象方法。
//注意抽象方法没有方法体,而且方法结束使用 ; 号。
abstract function getSal();
abstract function setSal();
//定义它的__tostring方法
public function __toString() {
return get_class($this);
}
}
?>
既然 User 类不能被直接继承,我们写一个 NormalUser 类继承自 User 类。当我们写成如下代码时,系统会报错。 这个错误告诉我们,在 User 类中有两个抽象方法,我们必须在子类中重写这两个方法。
<?php
abstract class User
{
protected $sal = 0;
//这里定义的抽象方法。
//注意抽象方法没有方法体,而且方法结束使用 ; 号。
abstract function getSal();
abstract function setSal();
//定义它的__tostring方法
public function __toString() {
return get_class($this);
}
}
class NormalUser extends User
{
}
?>
下面例子,重写了这两个方法,虽然方法体里面 {} 的内容是空的,也算重写了这个方法。注意看重写方法的参数名称,这里只要参数数量一致就可以,不要求参数的名称必须一致。
<?php
abstract class User
{
protected $sal = 0;
//这里定义的抽象方法。
//注意抽象方法没有方法体,而且方法结束使用;号。
abstract function getSal();
abstract function setSal();
//定义它的__tostring方法
public function __toString() {
return get_class($this);
}
}
class NormalUser extends User
{
function getSal() {
}
function setSal($sal) {
}
}
//这样就不会出错了。
?>
下面 19-21 行,三种写重写的方式都会报错。
19 行,缺少参数。
20 行,参数又多了。
21 行,参数类型不对。(这种写法在以后章节介绍)
一个类中,如果有一个抽象方法,这个类必须被声明为抽象类。
下面这个类不是抽象类,其中定义了一个抽象方法,会报错。
<?php
class User
{
protected $sal = 0;
//这里定义的抽象方法。
//注意抽象方法没有方法体,而且方法结束使用;号。
abstract function getSal();
abstract function setSal();
//定义它的__tostring方法
public function __toString() {
return get_class($this);
}
}
//这个类中有两个抽象方法,如果这个类不是抽象的。会报错
?>
抽象类继承抽象类
抽象类继承另外一个抽象类时,不用重写其中的抽象方法。
抽象类中,不能重写抽象父类的抽象方法。
这样的用法,可以理解为对抽象类的扩展
下面的例子,演示了一个抽象类继承自另外一个抽象类时,不需要重写其中的抽象方法。
<?php
abstract class User
{
protected $sal = 0;
abstract function getSal();
abstract function setSal($sal);
}
abstract class VipUser extends User
{
}
?>
抽象类在被继承后,其中的抽象方法不能被重写。
如果发生重写,系统会报错。
<?php
abstract class User
{
protected $sal = 0;
abstract function getSal();
abstract function setSal($sal);
}
abstract class VipUser extends User
{
abstract function setSal();
}
?>
抽象类继承抽象类,目的对抽象类的扩展。
<?php
abstract class User
{
protected $sal = 0;
abstract function getSal();
abstract function setSal($sal);
}
abstract class VipUser extends User
{
protected $commision = 0;
abstract function getCommision();
abstract function setCommision();
}
?>
在 PHP5.1 中,抽象类中支持静态抽象方法。下面这个例子,看到静态抽象方法可以声明。实现这个方法时,必须是静态的方法。
静态抽象方法
在 PHP5.1 中,抽象类中支持静态抽象方法。下面这个例子,看到静态抽象方法可以声明。实现这个方法时,必须是静态的方法。
<?php
abstract class User
{
protected static $sal = 0;
static abstract function getSal();
static abstract function setSal($sal);
}
class VipUser extends User
{
static function getSal() {
return self::$sal;
}
static function setSal($sal) {
self::$sal = $sal;
}
}
VipUser::setSal(100);
echo "you sal is " . VipUser::getSal();
?>
//这里的抽象方法好像没有问题
关于java -- static/final/abstract的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于4.11 abstract 类和 abstract 方法、5-2 Java 中的 static 使用之静态变量 ;;Java 中的 static 使用之静态方法;;Java 中的 static 使用之静态初始化块、Abstract vals && Abstract vars、abstract 类和 abstract 方法的相关知识,请在本站寻找。
本文标签: