对于想了解Enum.valueOf的读者,本文将提供新的信息,我们将详细介绍String方法从何而来?,并且为您提供关于CephRGW的usage数据从何而来?、javaindexof(Strings
对于想了解Enum.valueOf的读者,本文将提供新的信息,我们将详细介绍String方法从何而来?,并且为您提供关于Ceph RGW的usage数据从何而来?、java indexof(String str)方法的复杂性、Java String.valueOf(null)引发NPE,但是Object a = null;String.valueOf(a)返回'null'、Javadoc 1.5和1.6中缺少enum.valueOf(String name)的有价值信息。
本文目录一览:- Enum.valueOf(String)方法从何而来?(enum的valueof方法)
- Ceph RGW的usage数据从何而来?
- java indexof(String str)方法的复杂性
- Java String.valueOf(null)引发NPE,但是Object a = null;String.valueOf(a)返回'null'
- Javadoc 1.5和1.6中缺少enum.valueOf(String name)
Enum.valueOf(String)方法从何而来?(enum的valueof方法)
在Java SE 7中(并且很可能在以前的版本中),Enum类的声明如下:
public abstract class Enum<E extends Enum<E>> extends Object implements Comparable<E>, Serializable
Enum类具有带有此签名的静态方法:
T static<T extends Enum<T>> valueOf(Class<T> enumType, String name)
但是没有静态方法:valueOf(String)
在Enum类中定义,也不在Enum所属的层次结构中。
问题是valueOf(String)
从哪里来的?它是语言的功能,即编译器中内置的功能吗?
答案1
小编典典该方法由编译器隐式定义。
从文档中:
请注意,对于特定的枚举类型T,可以使用对该枚举上隐式声明的公共静态T
valueOf(String)方法来代替此方法,以从名称映射到相应的枚举常量。可以通过调用该类型的隐式公共静态T []
values()方法来获取枚举类型的所有常量。
根据Java语言规范的第8.9.2节:
另外,如果E是枚举类型的名称,则该类型具有以下隐式声明的静态方法:
/*** Returns an array containing the constants of this enum * type, in the order they''re declared. This method may be* used to iterate over the constants as follows:** for(E c : E.values())* System.out.println(c);** @return an array containing the constants of this enum * type, in the order they''re declared*/public static E[] values();/*** Returns the enum constant of this type with the specified* name.* The string must match exactly an identifier used to declare* an enum constant in this type. (Extraneous whitespace * characters are not permitted.)* * @return the enum constant with the specified name* @throws IllegalArgumentException if this enum type has no* constant with the specified name*/public static E valueOf(String name);
Ceph RGW的usage数据从何而来?
uRGW 的Usage信息是如何获取到的? 获取RGW的Usage信息,主要是来自于rgw_admin.cc中的函数:RGWUsage::show()。 这个函数定义在rgw/rgw_usage.h,实现于rgw/rgw_usage.cc 在文件rgw/rgw_usage.cc中可以看到函数的实现。 RGWUsage::show() 输入参数: RGWRados ×store (RGWRados类定义在rgw/rgw_rados.h中,) string& uid (用户名) uint64_t start_epoch(开始的时间) uint64_t end_epoch (结束的时间) ......
从store结构体中调用函数read_usage() 转到rgw/rgw_rados.h中,可以看到read_usage()的声明 在rgw/rgw_rados.cc中可以查看到read_usage()函数的实现。 可以看到read_usage()函数调用的是cls_obj_usage_log_read()。 cls_obj_usage_log_read()调用的是cls_rgw_usage_log_read() 在cls/rgw/cls_rgw_client.cc的249行:cls_rgw_usage_log_read()这个函数里: bufferlist in, out ::encode(call, in) 对bufferlist in进行编码处理,在函数exec中执行。 map<rgw_user_bucket, rgw_usage_log_entry> usage; void encode(bufferlist& bl) { ::encode()//表示这是一个全局函数。用于和局部或者成员函数来区分。 } iter是一个bufferlist迭代器类型。
io_ctx.exec是一个插件的动态加载函数,加载的函数是rgw_user_usage_log_read(),参数分别是in和out。 执行rgw_user_uage_log_read()函数实际上读取的真正的用户使用信息,将结果返回到out这个bufferlist中去。 然后从out中解码用户使用信息,将结果保存到result。 最终,result.usage被保存到了usage中。(由于usage是一个map<rgw_user_bucket, rgw_usage_log_entry>类型的引用,所以,此时就相当于直接修改了usage变量。) 也就是将结果保存到了usage中。
以上是各个函数的调用关系 当函数cls_rgw_usage_log_read()「rgw/cls_rgw_client.cc:249line」返回后,
返回到了调用它的函数RGWRados::cls_obj_usage_log_read()「rgw/rgw_rados.cc:6021line」 此时,已经将参数usage进行了设置。
然后,函数RGWRados::cls_obj_usage_log_read()继续返回,返回到调用它的函数:RGWRados::read_usage()函数。 在RGWRados::read_usage()这个函数中,会在循环条件之下,反复调用cls_obj_usage_log_read()这个函数。
其中,作为存储usage的相关数据结构就是map<rgw_user_bucket, rgw_usage_log_entry> 这是一个复合的数据结构, rgw_usage_log_entry
在io_ctx.exec中调用rgw_user_usage_log_read(),「这是一个封装在插件中的函数」 前一行的::encode(),是将call这个数据结构执行序列化操作,并将序列化操作放到in这个bufferlist中。 假设现在已经将call这个数据结构序列化到了in这个bufferlist中了。进入到rgw_user_usage_log_read()「位于cls/rgw/cls_rgw.cc:1199line」 这个函数的参数正好是bufferlist类型的in和out。 「可以看出,之前的call(rgw/cls_rgw_client.cc:257line)和这里的op是同一个数据类型。 1213 line的ret_info和rgw/cls_rgw_client.cc:269line的result也是同样的数据类型。」
在rgw_user_usage_log_read()函数中,首先对参数in进行反序列化操作,「即就是decode(op, in_iter)」.
反序列化后的结果保存在了op「类型rgw_cls_usage_log_read_op,和之前的call是一个类型的」 随后,使用一个map集合类型的指针变量usage指向了ret_info.usage「ret_info类型是rgw_cls_usage_log_read_ret,和result一致」 max_entries设置了最多能记录多少项。
函数usage_iterate_range(...,(void *)usage)最后是一个指针类型的参数,从后面的代码可以肯定,此函数修改了usage指示的内存地址内容。 而usage指示的内存地址如前所述,恰好是ret_info.usage指示的地址,所以usage_iterate_range()修改的是ret_info.usage的内容, 随后,下一行的encode执行序列化操作,将ret_info内容序列化到out中去。「这里也是间接的修改了out这个bufferlist内存区。」 最终,out指示的bufferlist内存区就存放了user_usage的内容。
现在,唯一还不明了的就是usage_iterate_range()这个函数了。 此函数位于cls/rgw/cls_rgw.cc:1099line 原型:static int usage_iterate_range(cls_method_context_t hctx, uint64_t start, uint64_t end, string& user, string& key_iter, uint32_t max_entries, bool *truncated, int (*cb)(cls_method_context_t, const string&, rgw_usage_log_entry&, void *), void *param)
再来看看位于1199行是如何调用int usage_iterate_range() 参数列表中依次是:hctx,开始的周期,结束周期,所有者,iter(?),最大记录项数量,是否分段,函数指针指向 usage_log_read_cb(), usage指针,指向了ret_info.usage。 即:hctx, op.start_epoch, op.end_epoch, op.owner, iter, max_entries, &ret_info.truncated, usage_log_read_cb, (void )usage /*******************************************************
****************************************************************************/
usage_record_prefix_by_time() usage_record_prefix_by_user() 这两个函数都是相当于在key这个字符串前面添加一些前缀比如时间或者user而已。
关键是cb指针所指向的函数。即就是:usage_log_read_cb() usage_log_read_cb的函数原型是(1189行): static int usage_log_read_cb(cls_method_context_t hctx, const string& key, rgw_usage_log_entry& entry, void *param) 这是一个静态函数。 在函数中usage_log_read_cb() 中,初始化了一个对象ub(entry.owner, entry.bucket) 但是,目前还有一个疑问,所取得的数据到底是从哪里获取的?
usage得到的那些信息,最初的来源就是从函数cls_cxx_map_get_vals() 「./objclass/class_api.cc」 「反正在cls_cxx_map_get_vals()中执行了一些乱七八糟的操作」就把值交给了keys,keys解码,将usage数据放到了
usage的原始数据从何而来,也就是记录的数据又是从哪里得到的? 参见rgw/rgw_log.cc:167,函数log_usage()
java indexof(String str)方法的复杂性
java indexof(Stringstr)方法的复杂性是什么?我的意思是,有像KMP这样的字符串匹配算法可以在线性时间内运行。我正在实现一个需要在非常大的字符串中搜索大子字符串的系统,因此我可以使用java
indexof(String str)方法还是应该实现KMP。
答案1
小编典典在Java的复杂执行的indexOf
是O(m*n)
其中n
并m
分别搜索字符串和模式的长度。
您可以采取的措施来提高复杂性,例如使用Boyer-
More算法来智能地跳过比较字符串中与模式不匹配的逻辑部分的比较。
Java String.valueOf(null)引发NPE,但是Object a = null;String.valueOf(a)返回'null'
是否存在以下行为的逻辑语言设计类型的解释(Java 7和我怀疑较早的版本):
Object a = null; String as = String.valueOf(a); // as is assigned "null" System.out.println(as+":"+as.length()); // prints: "null:4" System.out.println ( String.valueOf(null)); // NPE
答案1
小编典典在statement中System.out.println(String.valueOf(null));
有一个method的调用publicstatic String valueOf(char data[])
,其源代码如下:
public static String valueOf(char data[]) { return new String(data);}
那就是为什么你得到 NPE
另一方面,在statement中Object a = null; String as =String.valueOf(a);
有一个method的调用public static String valueOf(Objectobj)
,其源代码如下:
public static String valueOf(Object obj) { return (obj == null) ? "null" : obj.toString();}
这就是为什么您得到 “空” 而不是 NPE的原因
Java语言规范中的一些理论问题:15.12.2.5选择最具体的方法
如果多个成员方法既可访问又可应用于方法调用,则必须选择一个成员方法来为运行时方法分派提供描述符。 Java编程语言使用选择 最具体 方法的规则。
A char[]
是类型Object
,但不是全部Object
都是类型char[]
。型char[]
是 更具体的
比对象和作为Java语言规范所描述的,String.valueOf(char[])
过载被选择在这种情况下。
编辑
还值得一提的是伊恩·罗伯茨([IanRoberts提到的内容(在下面的评论中):
这是需要注意的重要的是它的,如果没有一个统一的超载比所有其他更具体的编译错误-
如果有一个valueOf(String)
方法,以及valueOf(Object)
和valueOf(char[])
随后的非类型化的调用String.valueOf(null)
是不明确
Javadoc 1.5和1.6中缺少enum.valueOf(String name)
这可能是一个愚蠢的问题,但是我正在使用method enum.valueOf(Stringname)
。那里没问题,只是当我检查javadoc以了解有关此方法的更多信息时,我找不到它。有Javadoc的,valueOf(Class<T>enumType, String name)
但没有一个 enum.valueOf(String name)
(这表明不存在具有此签名的方法-
但显然它存在)。
我在这里遗漏了什么吗,或者这是API的javadoc中的一个疏漏?
谢谢
答案1
小编典典没有方法Enum.valueOf(String)但是,每个方法enum
都有一个由编译器生成的values()
andvalueOf(String)
方法,这些都已记录在案。它们是静态方法,因此无法在超类或接口中覆盖或定义它们。
Enum e = Enum.valueOf(""); // this doesn''t compile
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.State.html#values%28%29
http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.State.html#values%28%29
在Java 5.0、6或7中相同。
对于Java 5.0
http://docs.oracle.com/javase/specs/jls/se5.0/html/classes.html#8.9(搜索值)对于Java
7 http://docs.oracle.com/javase/规格/ JLS / SE7 / HTML /
JLS-8.html#JLS-8.9.2通过@kapep提供
关于Enum.valueOf和String方法从何而来?的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于Ceph RGW的usage数据从何而来?、java indexof(String str)方法的复杂性、Java String.valueOf(null)引发NPE,但是Object a = null;String.valueOf(a)返回'null'、Javadoc 1.5和1.6中缺少enum.valueOf(String name)的相关信息,请在本站寻找。
本文标签: