Ⅰ Java靜態方法獲取所屬類的信息
靜態方法method(),只能把屬性也要設置成static的,才能訪問到你的屬性
但是你的目的:在方法體內部想獲取當前所屬類的類型信息
建議你可以這樣:舉個小例子
class
demo
{
private
int
num;
public
demo(){}
public
int
getNum()
{
return
this.num;
}//這個方法就很輕松的獲取你的屬性的信息;
}
o(∩_∩)o...希望你明白...
Ⅱ java如何獲取內部靜態類變數
靜態方法不與特定實例關聯,不能引用this,要得到當前類名,沒有直接的辦法。
通過查資料和試驗,可以用下面幾種方式:
public static void testGetClassName()
{
// 方法1:通過SecurityManager的保護方法getClassContext()
String clazzName = new SecurityManager()
{ public String getClassName()
{
return getClassContext()[1].getName();
}
}.getClassName();
System.out.println(clazzName);
// 方法2:通過Throwable的方法getStackTrace()
String clazzName2 = new Throwable().getStackTrace()[1].getClassName();
System.out.println(clazzName2);
// 方法3:通過分析匿名類名稱()
String clazzName3 = new Object() {
public String getClassName()
{
String clazzName = this.getClass().getName();
return clazzName.substring(0, clazzName.lastIndexOf('$'));
}
}.getClassName();
System.out.println(clazzName3);
}
分別調用10萬次,
方法1:219ms
方法2:953ms
方法3:31ms
Ⅲ 在靜態方法里,怎麼能得到調用者的類名
靜態方法本來就可以這樣調用的
A{
public:
static void a(){};
}
調用如下:
A::a();
Ⅳ 抽象類是怎樣通過調用靜態方法來獲取一個對象的
其實可以從jvm對class的載入來理解好理解有static的類或者方法或者屬性在jvm啟動時就會載入到內存所以你隨時可以調用但其他普通的並沒有載入所以你得用new關鍵字創建(其實就是內存里創建一個)才能調用
Ⅳ Java代碼中,如何在靜態(由static關鍵字修飾)方法或靜態代碼塊中(static{})獲取當前類的位置。。。
這是不可能的,static方法不隸屬於任何類/對象,所以無從獲取。static的內容由JVM統一管理,甚至都不在堆上.
看了你的補充說明。如果是想知道本靜態方法在哪個類被實現真的不可行,你的程序設計有錯誤。如果你是想讀取工作目錄下的一個文件,你只能知道改工作目錄的磁碟路徑,而文件名(類名)必須手工寫明,無法自動獲取。
Ⅵ 如何使用靜態方法,類方法或者抽象方法
方法是作為類的屬性(attribute)存儲的函數。你可以以下面的方式聲明和獲取函數:
>>> class Pizza(object):
... def __init__(self, size):
... self.size = size
... def get_size(self):
... return self.size
...
>>> Pizza.get_size
<unbound method Pizza.get_size>
Python告訴你的是,類Pizza的屬性get_size是一個非綁定的方法。這又指什麼呢?很快我們就會知道,試著調用一下:
>>> Pizza.get_size()
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
TypeError: unbound method get_size() must be called with Pizza instance as first argument (got nothing instead)
這里我們不能調用這個方法是因為它沒有被綁定到任一Pizza的實例上。一個方法需要一個實例作為它第一個參數(在Python 2中它必須是對應類的實例;在Python 3中可以是任何東西)。我們現在試試:
>>> Pizza.get_size(Pizza(42))
42
現在可以了!我們試用一個實例作為get_size方法的第一個參數調用了它,所以一切變得很美好。但是你很快會同意,這並不是一個很漂亮的調用方法的方式;因為每次我們想調用這個方法都必須使用到類。並且,如果我們不知道對象是哪個類的實例,這種方式就不方便了。
所以,Python為我們准備的是,它將類Pizza的所有的方法綁定到此類的任何實例上。這意味著類Pizza的任意實例的屬性get_size是一個已綁定的方法:第一個參數是實例本身的方法。
>>> Pizza(42).get_size
<bound method Pizza.get_size of <__main__.Pizza object at 0x10314b310>>
>>> Pizza(42).get_size()
42
如我們預期,現在不需要提供任何參數給get_size,因為它已經被綁定(bound),它的self參數是自動地設為Pizza類的實例。下面是一個更好的證明:
>>> m = Pizza(42).get_size
>>> m
<bound method Pizza.get_size of <__main__.Pizza object at 0x10314b350>>
>>> m()
42
因此,你甚至不要保存一個對Pizza對象的飲用。它的方法已經被綁定在對象上,所以這個方法已經足夠。
但是如何知道已綁定的方法被綁定在哪個對象上?技巧如下:
>>> m = Pizza(42).get_size
>>> m.__self__
<__main__.Pizza object at 0x10314b390>
>>> m == m.__self__.get_size
True
易見,我們仍然保存著一個對對象的引用,當需要知道時也可以找到。
在Python 3中,歸屬於一個類的函數不再被看成未綁定方法(unbound method),但是作為一個簡單的函數,如果要求可以綁定在對象上。所以,在Python 3中原理是一樣的,模型被簡化了。
>>> class Pizza(object):
... def __init__(self, size):
... self.size = size
... def get_size(self):
... return self.size
...
>>> Pizza.get_size
<function Pizza.get_size at 0x7f307f984dd0>
靜態方法
靜態方法是一類特殊的方法。有時,我們需要寫屬於一個類的方法,但是不需要用到對象本身。例如:
class Pizza(object):
@staticmethod
def mix_ingredients(x, y):
return x + y
def cook(self):
return self.mix_ingredients(self.cheese, self.vegetables)
這里,將方法mix_ingredients作為一個非靜態的方法也可以work,但是給它一個self的參數將沒有任何作用。這兒的decorator@staticmethod帶來一些特別的東西:
>>> Pizza().cook is Pizza().cook
False
>>> Pizza().mix_ingredients is Pizza().mix_ingredients
True
>>> Pizza().mix_ingredients is Pizza.mix_ingredients
True
>>> Pizza()
<__main__.Pizza object at 0x10314b410>
>>> Pizza()
<__main__.Pizza object at 0x10314b510>
>>>
Python不需要對每個實例化的Pizza對象實例化一個綁定的方法。綁定的方法同樣是對象,創建它們需要付出代價。這里的靜態方法避免了這樣的情況:
降低了閱讀代碼的難度:看到@staticmethod便知道這個方法不依賴與對象本身的狀態;
允許我們在子類中重載mix_ingredients方法。如果我們使用在模塊最頂層定義的函數mix_ingredients,一個繼承自Pizza的類若不重載cook,可能不可以改變混合成份(mix_ingredients)的方式。
類方法
什麼是類方法?類方法是綁定在類而非對象上的方法!
>>> class Pizza(object):
... radius = 42
... @classmethod
... def get_radius(cls):
... return cls.radius
...
>>> Pizza.get_radius
<bound method type.get_radius of <class '__main__.Pizza'>>
>>> Pizza().get_radius
<bound method type.get_radius of <class '__main__.Pizza'>>
>>> Pizza.get_radius is Pizza().get_radius
False
>>> Pizza.get_radius()
42
此處有問題。原文中
>>> Pizza.get_radius is Pizza().get_radius
True
還需要check一下。
不管你如何使用這個方法,它總會被綁定在其歸屬的類上,同時它第一個參數是類本身(記住:類同樣是對象)
何時使用這種方法?類方法一般用於下面兩種:
1. 工廠方法,被用來創建一個類的實例,完成一些預處理工作。如果我們使用一個@staticmethod靜態方法,我們可能需要在函數中硬編碼Pizza類的名稱,使得任何繼承自Pizza類的類不能使用我們的工廠用作自己的目的。
class Pizza(object):
def __init__(self, ingredients):
self.ingredients = ingredients
@classmethod
def from_fridge(cls, fridge):
return cls(fridge.get_cheese() + fridge.get_vegetables())
靜態方法調靜態方法:如果你將一個靜態方法分解為幾個靜態方法,你不需要硬編碼類名但可以使用類方法。使用這種方式來聲明我們的方法,Pizza這個名字不需要直接被引用,並且繼承和方法重載將會完美運作。
class Pizza(object):
def __init__(self, radius, height):
self.radius = radius
self.height = height
@staticmethod
def compute_circumference(radius):
return math.pi * (radius ** 2)
@classmethod
def compute_volume(cls, height, radius):
return height * cls.compute_circumference(radius)
def get_volume(self):
return self.compute_volume(self.height, self.radius)
抽象方法
抽象方法在一個基類中定義,但是可能不會有任何的實現。在Java中,這被描述為一個介面的方法。
所以Python中最簡單的抽象方法是:
class Pizza(object):
def get_radius(self):
raise NotImplementedError
任何繼承自Pizza的類將實現和重載get_radius方法,否則會出現異常。這種獨特的實現抽象方法的方式也有其缺點。如果你寫一個繼承自Pizza的類,忘記實現get_radius,錯誤將會在你使用這個方法的時候才會出現。
>>> Pizza()
<__main__.Pizza object at 0x106f381d0>
>>> Pizza().get_radius()
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
File "<stdin>", line 3, in get_radius
NotImplementedError
有種提前引起錯誤發生的方法,那就是當對象被實例化時,使用Python提供的abc模塊。
import abc
class BasePizza(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def get_radius(self):
"""Method that should do something."""
使用abc和它的特類,一旦你試著實例化BasePizza或者其他繼承自它的類,就會得到TypeError
>>> BasePizza()
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
TypeError: Can't instantiate abstract class BasePizza with abstract methods get_radius
混合靜態方法、類方法和抽象方法
當我們構建類和繼承關系時,終將會碰到要混合這些方法decorator的情況。下面提幾個tip。
記住聲明一個類為抽象類時,不要冷凍那個方法的prototype。這是指這個方法必須被實現,不過是可以使用任何參數列表來實現。
import abc
class BasePizza(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def get_ingredients(self):
"""Returns the ingredient list."""
class Calzone(BasePizza):
def get_ingredients(self, with_egg=False):
egg = Egg() if with_egg else None
return self.ingredients + egg
這個是合法的,因為Calzone完成了為BasePizza類對象定義的介面需求。就是說,我們可以把它當作一個類方法或者靜態方法來實現,例如:
import abc
class BasePizza(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def get_ingredients(self):
"""Returns the ingredient list."""
class DietPizza(BasePizza):
@staticmethod
def get_ingredients():
return None
這樣做同樣爭取,並且完成了與BasePizza抽象類達成一致的需求。get_ingredients方法不需要知道對象,這是實現的細節,而非完成需求的評價指標。
因此,你不能強迫抽象方法的實現是正常的方法、類方法或者靜態方法,並且可以這樣說,你不能。從Python 3開始(這就不會像在Python 2中那樣work了,見issue5867),現在可以在@abstractmethod之上使用@staticmethod和@classmethod了。
import abc
class BasePizza(object):
__metaclass__ = abc.ABCMeta
ingredient = ['cheese']
@classmethod
@abc.abstractmethod
def get_ingredients(cls):
"""Returns the ingredient list."""
return cls.ingredients
不要誤解:如果你認為這是強迫你的子類將get_ingredients實現為一個類方法,那就錯了。這個是表示你實現的get_ingredients在BasePizza類中是類方法而已。
在一個抽象方法的實現?是的!在Python中,對比與Java介面,你可以在抽象方法中寫代碼,並且使用super()調用:
import abc
class BasePizza(object):
__metaclass__ = abc.ABCMeta
default_ingredients = ['cheese']
@classmethod
@abc.abstractmethod
def get_ingredients(cls):
"""Returns the ingredient list."""
return cls.default_ingredients
class DietPizza(BasePizza):
def get_ingredients(self):
return ['egg'] + super(DietPizza, self).get_ingredients()
文/Not_GOD(簡書作者)
原文鏈接:http://www.jianshu.com/p/880d6a3ffdde
著作權歸作者所有,轉載請聯系作者獲得授權,並標注「簡書作者」。
Ⅶ 靜態方法怎麼調用
先在eclipse中創建一個Java工程文件。並在src下創建demo包,在demo包下創建類DemoClass。創建後的工程目錄如圖。
02
接下來在DemoClass類中添加一個靜態屬性和靜態方法。被static修飾的屬性或方法就是靜態的。
03
對於靜態方法的調用,可以使用調用非靜態方法的方式去調用,即創建一個類的對象,然後再調用靜態方法,具體代碼如下圖。
04
編輯好代碼後,通過java應用程序的方式運行DemoClass.java文件,運行結果如圖2,說明成功調用了靜態方法。
05
不過,上面調用靜態方法的方式是不推薦的。如果使用上面的方式調用靜態方法,在eclipse中,你可以看到下圖的警告,大概的意思是要你使用正確的調用靜態方法的方式去調用該方法。
06
對於靜態方法,正確調用的方式是直接通過類名來調用的。用調用例子中的staticFunction為例,正確調用該方法的代碼為
DemoClass.staticFunction。當用類來調用靜態方法時,可以看到eclipse就不報警告了。
07
再次運行該文件,運行結果和剛剛一樣,說明也成功調用了靜態方法。
08
多說一句,對於靜態屬性的調用,也是用類名+點+靜態屬性的方式來調用的,正常都不會先創建一個對象,然後再通過對象來調用靜態屬性。
Ⅷ 在java 中 父類定義的靜態方法 子類 調用時候 如何 知道 是哪個子類調用的
1)父類構造函數
java中當調用某個類的構造方法的時候,系統總會調用父類的非靜態初始化塊進行初始化,這個調用是隱式的,而且父類的靜態初始化代碼
塊總是會被執行,接著調用父類的一個或者多個構造器執行初始化,這個調用也可以通過super進行顯式調用。
例如:
父類代碼如下:
public class Creature {//父類
{//非靜態代碼塊
System.out.println("creature的非靜態代碼塊正在執行");
}
public Creature(){
System.out.println("creature的構造函數正在執行");
}
}
子類代碼如下:
public class Animal extends Creature {
{
System.out.println("animal的初始化代碼塊正在執行");
}
public Animal(){
System.out.println("animal的構造方法正在執行");
}
public static void main(String[] args){
Animal a = new Animal() ;
}
}
則運行程序後的結果為:
creature的非靜態代碼塊正在執行
creature的構造函數正在執行
animal的初始化代碼塊正在執行
animal的構造方法正在執行
從結果中可以看出:調用某個類的構造方法的時候總是會先執行父類的非靜態代碼塊,然後執行父類的構造方法,最後才是執行當前類的。
非靜態代碼塊和構造方法。執行過程中有先後順序。
若果想要顯式調用父類的構造方法則可以使用super(),來調用,但是super關鍵字和this關鍵字都必須放在構造放的第一行,而且只能使用第一個。
註:super用於顯式調用父類的構造器,this可以顯式調用本類中的重載的構造器。
2)訪問子類對象的實例變數
子類的方法可以訪問父類中的實例變數,這是因為子類繼承父類就會獲得父類中的成員變數和方法,但是父類方法不能訪問子類的實例變數,因為父類根本無法知道它將被哪個類繼承,它的子類將會增加怎麼樣的成員變數。但是,在極端的情況下,父類也可以訪問子類中的變數。
例如:
父類代碼如下:
public class Base {//父類
private int i = 2 ;
public Base(){
this.display() ;
}
public void display(){
System.out.println(i);
}
}
子類中代碼如下:
public class Derived extends Base {
private int i = 22 ;
public Derived(){
i = 222 ;
}
public void display(){
System.out.println(i);
}
}
測試用例如下:
public class Test {
public static void main(String[] args) {
new Derived() ;
}
}
程序的執行結果為:
0
調用new Derived() ;創建Derived
實例的時候,系統會為Derived對象分配內存空間,Derived會有兩個i實例變數,會分配兩個空間來保存i的值。分配完空間以後i的值為0
,如果有引用類型則引用類型的值為null。接下來程序在執行Derived的構造器之前會執行Base的構造器,表面上看Base的構造器中只有
一行代碼,但是在父類中定義i的時候執行的初始值2,因此經過編譯之後,該構造方法中應該包含如下兩行代碼:
i =2 ;
this.display() ;
程序先將Base中的i賦值為2,然後執行display方法。此處有一個關鍵字this,this到底代表誰呢?表面上看this代表的是Base的當前實例,但是實際上代碼是放在Derived的構造器中的,所以this最終代表的是Derived的當前實例(編譯類型是Base而實際引用一個Derived對象),所以如果在父類的構造方法中直接輸出System.out.println(this.i) ;則輸出的結果為2。但是調用this.display()方法,此時調用的是子類中重寫的display方法,輸出的變數i也是子類中的i,但是此時子類中的變數i還沒有賦值,所以輸出結果為0。
為了詳細的看清楚this變數到底代表什麼實例,我們將Base的構造方法修改如下:
public Base(){
System.out.println(this.i);
System.out.println(this.getClass());
this.display() ;
}
再次運行程序,結果為:
2
class e.qichao.chapter2.Derived
0
可以看到this代表的是Derived的實例,但是編譯的時候類型為Base,所以輸出this.i的值為2。
3)調用被子類重寫的方法
默認情況下,子類可以調用父類的方法,但是父類不能調用子類的方法,因為父類不知道它將被哪個子類繼承,也不知道子類將增加怎麼
樣的方法。
例如:
父類Animal的代碼如下:
public class Animal {
private String desc ;
public Animal(){
this.desc = getDesc() ;
}
public String getDesc(){
return "Animal" ;
}
public String toString(){
return desc ;
}
}
子類Wolf的代碼如下:
public class Wolf extends Animal {
private String name ;
private double weight ;
public Wolf(String name , double weight){
this.name = name ;
this.weight = weight ;
}
public String getDesc(){
return "Wolf[name=" + name + ",weight=" + weight + "]" ;
}
public static void main(String[] args){
System.out.println(new Wolf("灰太狼" , 3));
}
}
程序的運行結果為:
Wolf[name=null,weight=0.0]
在main方法中通過new Wolf("灰太狼" , 3);來創建一個Wolf的實例,子類會隱式調用父類的構造方法,在父類構造方法中初始化desc變數this.desc = getDesc() ;此處需要注意this變數,雖然這個this放在Animal的構造放中,但是是在Wolf的構造方法中調用父類的構造方法,所以this編譯時類型為Animal,運行時類型為Wolf,此處調用的getDesc方法是子類Wolf的方法,但是子類中的name和weight變數都沒有初始化,默認為null和0.0.所以程序的最終結果為:Wolf[name=null,weight=0.0]
4)繼承成員變數和成員方法的區別
java中隊成員變數的繼承和成員方法的繼承是不同的。
例如:
父類代碼如下:
public class Base {
int count = 2 ;
public void display(){
System.out.println(this.count);
}
}
子類代碼如下:
public class Derived extends Base {
int count = 20 ;
@Override
public void display(){
System.out.println(this.count);
}
}
測試用例如下:
public class Test {
public static void main(String[] args) {
Base b = new Base() ;
System.out.println(b.count);
b.display() ;
System.out.println("-----------------");
Derived d = new Derived() ;
System.out.println(d.count);
d.display() ;
System.out.println("-----------------");
Base bd = new Derived() ;
System.out.println(bd.count);
bd.display() ;
System.out.println("-----------------");
Base d2b = d ;
System.out.println(d2b.count);
}
}
程序運行結果為:
2
2
-----------------
20
20
-----------------
2
20
-----------------
2
Ⅸ 在靜態方法中如何獲得使用它的類類型
不用參數就用屬性
Class A
{
public string className="";
public static void A()
{
//想得到使用它的類類型
GetType();
}
}
Class B:A
{
}
調用
B.className = "B";
B.A();