Java中可以直接调用类中静态方法,不用实例化么,详解!原理

Java中可以直接调用类中静态方法,不用实例化么,详解!原理,第1张

好吧,我来试试看,看答案能不能够让你满意。

先通俗的分析下,我们把类看作是一个房子。房子里面有家具,桌椅板凳之类的,房子里面还有人。

房子里面所有的人都应该是共有一套家具的。也就是说,这些家具是唯一的,如果某个家具坏了,那么大家都用不了。

我们再看一看定义,java的静态变量也叫做类变量,它开始于类的创建,结束于类的消亡。非静态变量叫做实例变量,它开始于类的实例的创建,结束语类的实例的消亡。静态变量被所有实例所共享。也就是如上面的例子,座椅板凳是类变量,它们是在房子被建好了之后就被添加放置进来,而且基本都是唯一的。人就相当于实例,每个人都能用这些家具,但是如果家具一旦损坏,那就是坏了,或者你把某一个家具搬走,那么所有的人都用不了这个家具,房子里也不存在这个家具了。

但是房子里可以进很多人,可以进张三,也可以进李四。所以这些人就是类的实例对象,他们身上穿的衣服就可以叫做实例变量。

那么在内存之中又是如何的呢?当一个类被创建并初始化后,内存中会有两个区域,栈区和堆区。栈中主要存放的是引用变量,堆中主要存放的是真实的被实例化后的类。栈中的引用变量会指向堆中的真实对象地址。比如A a=new A(); a这个变量就会在栈中,实际被new出来的类A的对象会放在堆中,a指向实际被new出来的A对象。

如果一个类中有静态变量的话,程序首先会把该静态变量加载进内存中,也就是在堆中开辟一个区域专门存放。以后不管你new多少个类的对象,该静态变量永远都是在那里的。也就是说,静态变量在类的初始化一次后,系统就不会为该变量开辟新的内存空间。而每new一个类的对象,系统就会重新在

堆内存中开辟一个新空间来存放该类的实例对象,并且栈中也会有一个新的引用变量去指向它。

静态方法也是类似,但是有一点要强调,静态方法只中不能调用非静态方法。因为被static修饰的方法会首先被Classloader对象先加载进内存,而这个时候可能其它的非静态方法或者变量还没有被加载进来。就好比我现在想做包子,现在面粉被static修饰,首先已经拿到你身边,可是因为包子馅不是static修饰的,所以可能包子馅儿还没运过来,你说怎么做的出包子呢。

被static修饰过的都是随着类的初始化后就产生了,在堆内存中都有一块专门的区域来存放,所以只需要类名点方法名或者变量名即可。而非静态的就必须通过类的对象去调相应的。就像是你想要红色的衣服,你必须是从穿红色的衣服的人的身上拿过来才行,所以你必须找到穿红色衣服的人,也就是类的实例对象,而你如果要去找一个桌子,而桌子就在房间里摆着,你只要进到房间里直接走过去拿来就可以了~~

1类方法用@classmethod:

        用途:一般用来对类属性进行限制性 *** 作

        用法:该方法的调用者(不管是类调用还是实例调用),会默认把该类作为第一个参数传进来(调用者不必显示指定),这样该方法内部可以获取到该类,从而对类属性进行 *** 作。实际用途可以用来限制对类属性的访问,不管是类调用还是实例调用,能保证修改的都是类属性。

2静态方法用@staticmethod:

        用途:用来实现工具性方法

        用法:如果方法内部没有涉及到对实例属性的 *** 作,可以把该方法定义为静态方法,不管是类调用还是实例调用,都能直接调用该方法实现相应功能。

3普通方法:

        用途:实例调用的方法

        用法:方法内部涉及到对实例属性的 *** 作,实例调用该方法时会自动默认将实例的引用作为第一个参数传进去。也可以用类直接访问,不过这样访问时需要手动传入第一个参数,也就是一个实例的引用。

附加: @property的使用(从语义规范上来说,只用于普通方法,也就是对实例变量进行控制,但也可以强行用来对类变量进行控制)

对私有变量的控制访问可以借鉴java的get、set方式。这没有任何问题。唯一的问题就是不直观,把对变量的访问变成了对方法的访问。而@property的作用就是还原这种直观的访问方式,可以像访问变量一样访问@property修饰的方法。注意:如果不想让别人修改某变量,可以用不写@XXXsetter方法来实现。

总结:不管方法是哪一种方法(类方法,静态方法,还是普通的实例方法),都可以用类直接访问和用实例进行访问,只是参数多传一个多传一个的问题。更重要的是语义的规范,语法上没什么问题。

一个javalangClass对象代表了Java应用程序在运行时所加载的类或接口实例,也就是说被加载的类在JVM中以Class的实例存在,Class对象由JVM自动产生。通过Object的getClass()方法来获取每一个对象对应的Class对象,或的Class对象之后可以用Class对象上的方法取得类的信息。

在一些应用程序中,无法事先知道用户将加载什么类,而必须用户指定类名称以加载类,可以用Class的静态方法forName()方法实现动态加载类。forClass()我不知道是做什么的。下面是例子:

import javalangreflect;

public class ClassDemo

{

public static void main(String[] args)

{

Systemoutprintln("getClass()的例子\n");

String name="john";

//获得name对象的Class实例

Class stringClass=namegetClass();

//下面可以用stringClass实例获取name对象的相关信息,可以看API文档,这里只举两个方法

Systemoutprintln("name对象的类型:"+stringClassgetName());

Systemoutprintln("name对象的父类:"+stringClassgetSuperclass()getName());

Systemoutprintln("\nforName()的例子\n");

//举forName()的例子

//动态加载javautilArrayList类

//得到类的Class实例后利用Class的方法取得类相关信息

//里面有好多方法我就不解释了,你可以参考API文档

try

{

Class c=ClassforName("javautilArrayList");

int mod=cgetModifiers();

Systemoutprint(ModifiertoString(mod));

if(ModifierisInterface(mod))

Systemoutprint(" interface");

else

Systemoutprint(" class ");

Systemoutprintln(cgetName()+"{");

Systemoutprintln("\t//成员变量");

Field[] field=cgetDeclaredFields();

for(Field f:field)

{

Systemoutprint("\t"+ModifiertoString(fgetModifiers()));

Systemoutprint(" "+fgetType()getName());

Systemoutprintln(" "+fgetName()+";");

}

Systemoutprintln("\t//构造方法");

Constructor[] constructor=cgetDeclaredConstructors();

for(Constructor con:constructor)

{

Systemoutprint("\t"+ModifiertoString(congetModifiers()));

Systemoutprintln(" "+congetName()+"();");

}

Systemoutprintln("\t//成员方法");

Method[] method=cgetDeclaredMethods();

for(Method mhd:method)

{

Systemoutprint("\t"+ModifiertoString((mhdgetModifiers())));

Systemoutprint(" "+mhdgetReturnType()getName());

Systemoutprintln(" "+mhdgetName()+"()");

}

Systemoutprintln("}");

}

catch(Exception e)

{

eprintStackTrace();

}

}

}

以上就是关于Java中可以直接调用类中静态方法,不用实例化么,详解!原理全部的内容,包括:Java中可以直接调用类中静态方法,不用实例化么,详解!原理、python 类方法,静态方法,普通方法比较2019-03-22、关于forClass,getClass,forName方法等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/10182681.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-06
下一篇2023-05-06

发表评论

登录后才能评论

评论列表(0条)

    保存