__attribute__ 总结

28 篇文章 0 订阅
               
 
 

attribute是GNU C特色之一,在iOS用的比较广泛.系统中有许多地方使用到. attribute可以设置函数属性(Function Attribute )、变量属性(Variable Attribute )和类型属性(Type Attribute)等.

函数属性(Function Attribute)

  • noreturn
  • noinline
  • always_inline
  • pure
  • const
  • nothrow
  • sentinel
  • format
  • format_arg
  • no_instrument_function
  • section
  • constructor
  • destructor
  • used
  • unused
  • deprecated
  • weak
  • malloc
  • alias
  • warn_unused_result
  • nonnull

类型属性(Type Attributes)

  • aligned
  • packed
  • transparent_union,
  • unused,
  • deprecated
  • may_alias

变量属性(Variable Attribute)

  • aligned
  • packed

Clang特有的

  • availability
  • overloadable

书写格式

书写格式:attribute后面会紧跟一对原括弧,括弧里面是相应的attribute参数

__attribute__(xxx)
   
   

常见的系统用法

format

官方例子:NSLog

 #define NS_FORMAT_FUNCTION(F,A) __attribute__((format(__NSString__, F, A)))
   
   

format属性可以给被声明的函数加上类似printf或者scanf的特征,它可以使编译器检查函数声明和函数实际调用参数之间的格式化字符串是否匹配。该功能十分有用,尤其是处理一些很难发现的bug。对于format参数的使用如下
format (archetype, string-index, first-to-check)
第一参数需要传递“archetype”指定是哪种风格,这里是 NSString;“string-index”指定传入函数的第几个参数是格式化字符串;“first-to-check”指定第一个可变参数所在的索引.

noreturn

官方例子: abort() 和 exit()

该属性通知编译器函数从不返回值。当遇到类似函数还未运行到return语句就需要退出来的情况,该属性可以避免出现错误信息。

availability

官方例子:


   
   
  1. - ( CGSize)sizeWithFont:( UIFont *)font NS_DEPRECATED_IOS( 2_0, 7_0, "Use -sizeWithAttributes:") __TVOS_PROHIBITED;
  2. //来看一下 后边的宏
  3. #define NS_DEPRECATED_IOS(_iosIntro, _iosDep, ...) CF_DEPRECATED_IOS(_iosIntro, _iosDep, __VA_ARGS__)
  4. define CF_DEPRECATED_IOS(_iosIntro, _iosDep, ...) __attribute__((availability(ios,introduced=_iosIntro,deprecated=_iosDep,message= "" __VA_ARGS__)))
  5. //宏展开以后如下
  6. __attribute__((availability(ios,introduced= 2_0,deprecated= 7_0,message= ""__VA_ARGS__)));
  7. //ios即是iOS平台
  8. //introduced 从哪个版本开始使用
  9. //deprecated 从哪个版本开始弃用
  10. //message    警告的消息

availability属性是一个以逗号为分隔的参数列表,以平台的名称开始,包含一些放在附加信息里的一些里程碑式的声明。

  • introduced:第一次出现的版本。

  • deprecated:声明要废弃的版本,意味着用户要迁移为其他API

  • obsoleted: 声明移除的版本,意味着完全移除,再也不能使用它

  • unavailable:在这些平台不可用

  • message:一些关于废弃和移除的额外信息,clang发出警告的时候会提供这些信息,对用户使用替代的API非常有用。

  • 这个属性支持的平台:ios,macosx。

简单例子:


   
   
  1. //如果经常用,建议定义成类似系统的宏
  2. - ( void)oldMethod:( NSString *)string __attribute__((availability(ios,introduced= 2_0,deprecated= 7_0,message= "用 -newMethod: 这个方法替代 "))){
  3.     NSLog( @"我是旧方法,不要调我");
  4. }
  5. - ( void)newMethod:( NSString *)string{
  6.     NSLog( @"我是新方法");
  7. }

效果:


Paste_Image.png

//如果调用了,会有警告


Paste_Image.png
unavailable

告诉编译器该方法不可用,如果强行调用编译器会提示错误。比如某个类在构造的时候不想直接通过init来初始化,只能通过特定的初始化方法()比如单例,就可以将init方法标记为unavailable;


   
   
  1. //系统的宏,可以直接拿来用
  2. #define UNAVAILABLE_ATTRIBUTE __attribute__((unavailable))
  3. #define NS_UNAVAILABLE UNAVAILABLE_ATTRIBUTE

   
   
  1. @interface Person : NSObject
  2. @property( nonatomic, copy) NSString *name;
  3. @property( nonatomic, assign) NSUInteger age;
  4. - ( instancetype)init NS_UNAVAILABLE;
  5. - ( instancetype)initWithName:( NSString *)name age:( NSUInteger)age;
  6. @end

Paste_Image.png

//实际上unavailable后面可以跟参数,显示一些信息,如:


   
   
  1. //系统的
  2. #define NS_AUTOMATED_REFCOUNT_UNAVAILABLE __attribute__((unavailable("not available in automatic reference counting mode")))
objc_root_class

表示这个类是一个根类(基类),比如NSObject,NSProxy.


   
   
  1. //摘自系统
  2. //NSProxy
  3. NS_ROOT_CLASS
  4. @interface NSProxy <NSObject> {
  5.     Class    isa;
  6. }
  7. //NSObject
  8. __OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0)
  9. OBJC_ROOT_CLASS
  10. OBJC_EXPORT
  11. @interface NSObject <NSObject> {
  12.     Class isa  OBJC_ISA_AVAILABILITY;
  13. }
NSObject
@property (nonatomic,strong) __attribute__((NSObject)) CFDictionaryRef myDictionary;
   
   

CFDictionaryRef属于CoreFoundation框架的,也就是非OC对象,加上attribute((NSObject))后,myDictionary的内存管理会被当做OC对象来对待.

objc_designated_initializer

用来修饰类的designated initializer初始化方法,如果修饰的方法里没有调用super类的 designated initializer,编译器会发出警告。可以简写成NS_DESIGNATED_INITIALIZER

这篇文章讲的很好,建议参考这个.
https://yq.aliyun.com/articles/5847

visibility

语法:

__attribute__((visibility("visibility_type")))
   
   

其中,visibility_type 是下列值之一:

  • default
    假定的符号可见性可通过其他选项进行更改。缺省可见性将覆盖此类更改。缺省可见性与外部链接对应。

  • hidden
    该符号不存放在动态符号表中,因此,其他可执行文件或共享库都无法直接引用它。使用函数指针可进行间接引用。

  • internal
    除非由 特定于处理器的应用二进制接口 (psABI) 指定,否则,内部可见性意味着不允许从另一模块调用该函数。

  • protected
    该符号存放在动态符号表中,但定义模块内的引用将与局部符号绑定。也就是说,另一模块无法覆盖该符号。

  • 除指定 default 可见性外,此属性都可与在这些情况下具有外部链接的声明结合使用。
    您可在 C 和 C++ 中使用此属性。在 C++ 中,还可将它应用于类型、成员函数和命名空间声明。

系统用法:


   
   
  1. //  UIKIT_EXTERN     extern
  2. #ifdef __cplusplus
  3. #define UIKIT_EXTERN        extern "C" __attribute__((visibility ("default")))
  4. #else
  5. #define UIKIT_EXTERN            extern __attribute__((visibility ("default")))
  6. #endif
  7. `
nonnull

编译器对函数参数进行NULL的检查,参数类型必须是指针类型(包括对象)
//使用


   
   
  1. - ( int)addNum1:( int *)num1 num2:( int *)num2  __attribute__(( nonnull ( 1, 2))){ //1,2表示第一个和第二个参数不能为空
  2.     return  *num1 + *num2;
  3. }
  4. - ( NSString *)getHost:( NSURL *)url __attribute__(( nonnull ( 1))){ //第一个参数不能为空
  5.     return url.host;
  6. }

常见用法

aligned

__attribute((aligned (n))),让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐.例如:

不加修饰的情况


   
   
  1. typedef struct
  2. {
  3.     char  member1;
  4.     int   member2;
  5.     short member3;
  6. }Family;
  7. //输出字节:
  8. NSLog( @"Family size is %zd", sizeof(Family));
  9. //输出结果为:
  10. 2016 -07 -25 10: 28: 45.380 Study[ 917: 436064] Family size is 12

//修改字节对齐为1


   
   
  1. typedef struct
  2. {
  3.     char  member1;
  4.     int   member2;
  5.     short member3;
  6. }__attribute__ ((aligned ( 1))) Family;
  7. //输出字节:
  8. NSLog( @"Family size is %zd", sizeof(Family));
  9. //输出结果为:
  10. 2016 -07 -25 10: 28: 05.315 Study[ 914: 435764] Family size is 12

和上面的结果一致,因为 设定的字节对齐为1.而结构体中成员的最大字节数是int 4个字节,1 < 4,按照4字节对齐,和系统默认一致.

修改字节对齐为8


   
   
  1. typedef struct
  2. {
  3.     char  member1;
  4.     int   member2;
  5.     short member3;
  6. }__attribute__ ((aligned ( 8))) Family;
  7. //输出字节:
  8. NSLog( @"Family size is %zd", sizeof(Family));
  9. //输出结果为:
  10. 2016 -07 -25 10: 28: 05.315 Study[ 914: 435764] Family size is 16

这里 8 > 4,按照8字节对齐,结果为16,不知道字节对齐的可以看我的这篇文章http://www.jianshu.com/p/f69652c7df99

可是想了半天,也不知道这玩意有什么用,设定值小于系统默认的,和没设定一样,设定大了,又浪费空间,效率也没提高,感觉学习学习就好.

packed

让指定的结构结构体按照一字节对齐,测试:


   
   
  1. //不加packed修饰
  2. typedef struct {
  3.     char    version;
  4.     int16_t sid;
  5.     int32_t len;
  6.     int64_t time;
  7. } Header;
  8. //计算长度
  9. NSLog(@ "size is %zd", sizeof(Header));
  10. 输出结果为:
  11. 2016 -07 -22 11: 53: 47.728 Study[ 14378: 5523450] size is 16

可以看出,默认系统是按照4字节对齐


   
   
  1. //加packed修饰
  2. typedef struct {
  3.     char    version;
  4.     int16_t sid;
  5.     int32_t len;
  6.     int64_t time;
  7. }__attribute__ ((packed)) Header;
  8. //计算长度
  9. NSLog(@ "size is %zd", sizeof(Header));
  10. 输出结果为:
  11. 2016 -07 -22 11: 57: 46.970 Study[ 14382: 5524502] size is 15

用packed修饰后,变为1字节对齐,这个常用于与协议有关的网络传输中.

noinline  & always_inline

内联函数:内联函数从源代码层看,有函数的结构,而在编译后,却不具备函数的性质。内联函数不是在调用时发生控制转移,而是在编译时将函数体嵌入在每一个调用处。编译时,类似宏替换,使用函数体替换调用处的函数名。一般在代码中用inline修饰,但是能否形成内联函数,需要看编译器对该函数定义的具体处理

  • noinline 不内联
  • always_inline 总是内联
  • 这两个都是用在函数上

内联的本质是用代码块直接替换掉函数调用处,好处是:快代码的执行,减少系统开销.适用场景:

  • 这个函数更小
  • 这个函数不被经常调用

使用例子:


   
   
  1. //函数声明
  2. void test(int a) __attribute__((always_inline));
warn_unused_result

  当函数或者方法的返回值很重要时,要求调用者必须检查或者使用返回值,否则编译器会发出警告提示


   
   
  1. - (BOOL) availiable __attribute__((warn_unused_result))
  2. {
  3.     return 10;
  4. }

警告如下:


Paste_Image.png
objc_subclassing_restricted

因为某些原因,我们不希望这个类被继承,也就是 "最终"的类,用法如下:


   
   
  1. __attribute__((objc_subclassing_restricted))
  2. @interface ViewController : UIViewController
  3. @end

如果继承了这个类,编译器会报错


Paste_Image.png
objc_requires_super

这个属性要求子类在重写父类的方法时,必须要重载父类方法,也就是调用super方法,否则警告.示例如下:


   
   
  1. @interface ViewController : UIViewController
  2. - ( void)jump __attribute__((objc_requires_super));
  3. @end
  4. - ( void)jump{
  5.     NSLog( @"父类必须先执行");
  6. }
  7. @interface SGViewController : ViewController
  8. @end
  9. @implementation SGViewController
  10. - ( void)jump{
  11.     NSLog( @"子类才能再执行");
  12. }
  13. @end

警告如下:


Paste_Image.png
objc_boxable

实现类似于NSNumber 的快速打包能力@(...),一般对于struct,union我们只能通过NSValue将其打包. objc_boxable 可以帮助我们实现快速打包,示例如下:


   
   
  1. //自定义结构体
  2. typedef struct __attribute__((objc_boxable)){
  3.     CGFloat x,y,width,height;
  4. }SGRect;
  5. SGRect rect = { 0, 0, 100, 200};
  6. //这里直接打包成NSValue
  7. NSValue *value = @(rect);
  8. //这里我直接用系统的方法打印
  9. NSLog( @"%@", NSStringFromCGRect(value.CGRectValue));
  10. 输出:
  11. 2016 -07 -21 21: 28: 43.538 Study[ 14118: 5408921] {{ 0, 0}, { 100, 200}}

这样SGRect就具备快速打包功能了.

constructor / destructor

意思是: 构造器和析构器;constructor修饰的函数会在main函数之前执行,destructor修饰的函数会在程序exit前调用.
示例如下:


   
   
  1. int main( int argc, char * argv[]) {
  2.     @autoreleasepool {
  3.         NSLog( @"main");
  4.         return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
  5.     }
  6. }
  7. __attribute__((constructor))
  8. void  before(){
  9.     NSLog( @"before main");
  10. }
  11. __attribute__((destructor))
  12. void  after(){
  13.     NSLog( @"after main");
  14. }
  15. //在viewController中调用exit
  16. - ( void)viewDidLoad {
  17.     [ super viewDidLoad];
  18.     exit( 0);
  19. }
  20. 输出如下:
  21. 2016 -07 -21 21: 49: 17.446 Study[ 14162: 5415982] before main
  22. 2016 -07 -21 21: 49: 17.447 Study[ 14162: 5415982] main
  23. 2016 -07 -21 21: 49: 17.534 Study[ 14162: 5415982] after main

注意点:

  • 程序退出的时候才会调用after函数,经测试,手动退出程序会执行
  • 上面两个函数不管写在哪个类里,哪个文件中效果都一样
  • 如果存在多个修饰的函数,那么都会执行,顺序不定

实际上如果存在多个修饰过的函数,可以它们的调整优先级
代码如下:


   
   
  1. int main( int argc, char * argv[]) {
  2.     @autoreleasepool {
  3.         NSLog( @"main");
  4.         return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
  5.     }
  6. }
  7. __attribute__((constructor( 101)))
  8. void  before1(){
  9.     NSLog( @"before main - 1");
  10. }
  11. __attribute__((constructor( 102)))
  12. void  before2(){
  13.     NSLog( @"before main - 2");
  14. }
  15. __attribute__((destructor( 201)))
  16. void  after1(){
  17.     NSLog( @"after main - 1");
  18. }
  19. __attribute__((destructor( 202)))
  20. void  after2(){
  21.     NSLog( @"after main - 2");
  22. }
  23. 输出结果如下:
  24. 2016 -07 -21 21: 59: 35.622 Study[ 14171: 5418393] before main - 1
  25. 2016 -07 -21 21: 59: 35.624 Study[ 14171: 5418393] before main - 2
  26. 2016 -07 -21 21: 59: 35.624 Study[ 14171: 5418393] main
  27. 2016 -07 -21 21: 59: 35.704 Study[ 14171: 5418393] after main - 2
  28. 2016 -07 -21 21: 59: 35.704 Study[ 14171: 5418393] after main - 1

注意点:

  • 括号内的值表示优先级,[0,100]这个返回时系统保留的,自己千万别调用.
  • 根据输出结果可以看出,main函数之前的,数值越小,越先调用;main函数之后的数值越大,越先调用.

当函数声明和函数实现分开写时,格式如下:


   
   
  1. static void before() __attribute__(( constructor));
  2. static void before() {
  3.     printf("before\n");
  4. }

讨论:+load,constructor,main的执行顺序,代码如下:


   
   
  1. + (void)load {
  2.     NSLog(@"load");
  3. }
  4. __attribute__(( constructor))
  5. void  before () {
  6.     NSLog(@"before main");
  7. }
  8. 输出结果如下:
  9. 2016- 07- 21 22: 13: 58.591 Study[ 14185: 5421811] load
  10. 2016- 07- 21 22: 13: 58.592 Study[ 14185: 5421811] before main
  11. 2016- 07- 21 22: 13: 58.592 Study[ 14185: 5421811] main

可以看出执行顺序为:
load->constructor->main
为什么呢?
因为 dyld(动态链接器,程序的最初起点)在加载 image(可以理解成 Mach-O 文件)时会先通知 objc runtime 去加载其中所有的类,每加载一个类时,它的 +load 随之调用,全部加载完成后,dyld 才会调用这个 image 中所有的 constructor 方法,然后才调用main函数.

enable_if

用来检查参数是否合法,只能用来修饰函数:


   
   
  1. void printAge(int age)
  2. __attribute__ ((enable_if(age > 0  && age < 120, "你丫太监?")))
  3. {
  4.     NSLog(@ "%d",age);
  5. }

表示只能输入的参数只能是 0 ~ 120左右,否则编译报错
报错如下:


Paste_Image.png
cleanup

声明到一个变量上,当这个变量作用域结束时,调用指定的一个函数.如果不知道什么是作用域,请先学习一下.例子:


   
   
  1. //这里传递的参数是变量的地址
  2. void intCleanup(int *num){
  3.     NSLog(@ "cleanup------%d",*num);
  4. }
  5. - ( void)test{
  6.   int a __attribute__((cleanup(intCleanup))) = 10;
  7. }
  8. 输出结果为:
  9. 2016- 07- 22 09: 59: 09.139 Study[ 14293: 5495713] cleanup------ 10

注意点:

  • 指定的函数传递的参数是变量的地址
  • 作用域的结束包括:大括号结束、return、goto、break、exception等情况
  • 当作用域内有多个cleanup的变量时,遵守 先入后出 的栈式结构.

示例代码:


   
   
  1. void intCleanup( int *num){
  2.     NSLog( @"cleanup------%d",*num);
  3. }
  4. void stringCleanup( NSString **str){
  5.     NSLog( @"cleanup------%@",*str);
  6. }
  7. void rectCleanup( CGRect *rect){
  8.     CGRect temp = *rect;
  9.     NSString *str = NSStringFromCGRect(temp);
  10.     NSLog( @"cleanup------%@",str);
  11. }
  12. int a __attribute__((cleanup(intCleanup))) = 10;
  13.     {
  14.         NSString *string __attribute__((cleanup(stringCleanup))) = @"string";
  15.         CGRect rect __attribute__((cleanup(rectCleanup))) = { 0, 0, 1, 1};
  16.     }
  17.     输出结果为:
  18.     2016 -07 -22 10: 09: 36.621 Study[ 14308: 5498861] cleanup------{{ 0, 0}, { 1, 1}}
  19. 2016 -07 -22 10: 09: 36.622 Study[ 14308: 5498861] cleanup------string
  20. 2016 -07 -22 10: 09: 36.622 Study[ 14308: 5498861] cleanup----- -10

讨论:如果修饰了某个对象,那么cleanup和dealloc,谁先执行?
测试代码如下:


   
   
  1. void objectCleanup( NSObject **obj){
  2.     NSLog( @"cleanup------%@",*obj);
  3. }
  4. - ( void)viewDidLoad {
  5.     [ super viewDidLoad];
  6.     ViewController *vc __attribute__((cleanup(objectCleanup))) = [[ViewController alloc] init];
  7. }
  8. - ( void)dealloc{
  9.     NSLog( @"dealloc");
  10. }
  11. 输出结果如下:
  12. 2016 -07 -22 10: 23: 08.839 Study[ 14319: 5502769] cleanup------<ViewController: 0x13fe881e0>
  13. 2016 -07 -22 10: 23: 08.840 Study[ 14319: 5502769] dealloc

可以明显看出,cleanup先于对象的dealloc执行.

  • 在block中的用法:在block中使用,先看例子:

   
   
  1. //指向block的指针,觉得不好理解可以用typeof
  2. void blockCleanUp(void(^*block)()){
  3.     (*block)();
  4. }
  5. void (^block)( void) __attribute__((cleanup(blockCleanUp))) = ^{
  6.         NSLog(@ "finish block");
  7.     };

这个好处就是,不用等到block最后才写某些代码,我们可以把它放在block的任意位置,防止忘记.

overloadable

用于c语言函数,可以定义若干个函数名相同,但参数不同的方法,调用时编译器会自动根据参数选择函数原型:


   
   
  1. __attribute__((overloadable)) void print(NSString * string){
  2.     NSLog(@ "%@", string);
  3. }
  4. __attribute__((overloadable)) void print( int num){
  5.     NSLog(@ "%d",num);
  6. }
  7. //调用
  8. print( 10);
  9. print(@ "哈哈");
objc_runtime_name

看到runtime是不是就感觉高大上,没错这个也跟运行时有关.作用是将将类或协议的名字在编译时指定成另一个.示例如下:


   
   
  1. __attribute__((objc_runtime_name( "NSObject")))
  2. @interface SGObject :NSObject
  3. @end
  4. //调用
  5. NSLog( @"%@",[SGObject class]);
  6. //输出
  7. 2016 -07 -22 11: 18: 00.934 Study[ 14355: 5516261] NSObject

可以用来做代码混淆.

更多请看官网:
https://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Function-Attributes.html



转载自:http://www.jianshu.com/p/29eb7b5c8b2d

           
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JAVA相关基础知识 1、面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。 2.继承: 继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。 3.封装: 封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。 4. 多态性: 多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。 2、String是最基本的数据类型吗? 基本数据类型包括byte、int、char、long、float、double、boolean和short。 java.lang.String类是final类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用StringBuffer类 3、int 和 Integer 有什么区别 Java 提供两种不同的类型:引用类型和原始类型(或内置类型)。Int是java的原始数据类型,Integer是java为int提供的封装类。Java为每个原始类型提供了封装类。 原始类型封装类 booleanBoolean charCharacter byteByte shortShort intInteger longLong floatFloat doubleDouble 引用类型和原始类型的行为完全不同,并且它们具有不同的语义。引用类型和原始类型具有不同的特征和用法,它们包括:大小和速度问题,这种类型以哪种类型的数据结构存储,当引用类型和原始类型用作某个类的实例数据时所指定的缺省值。对象引用实例变量的缺省值为 null,而原始类型实例变量的缺省值与它们的类型有关。 4、String 和StringBuffer的区别 JAVA平台提供了两个类:String和StringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据。这个String类提供了数值不可改变的字符串。而这个StringBuffer类提供的字符串进行修改。当你知道字符数据要改变的时候你就可以使用StringBuffer。典型地,你可以使用StringBuffers来动态构造字符数据。 5、运行时异常与一般异常有何异同? 异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。 6、说出Servlet的生命周期,并说出Servlet和CGI的区别。 Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,当服务器决定将实例销毁的时候调用其destroy方法。 与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。 7、说出ArrayList,Vector, LinkedList的存储性能和特性 ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。 8、EJB是基于哪些技术实现的?并说出SessionBean和EntityBean的区别,StatefulBean和StatelessBean的区别。 EJB包括Session Bean、Entity Bean、Message Driven Bea
### 回答1: 这个错误提示意味着在调用Python的vars()函数时,传入的参数不是一个带有__dict__属性的对象。vars()函数用于返回一个对象的属性和属性值的字典。 通常情况下,vars()函数可以接受任何具有__dict__属性的对象作为参数,例如Python内置的对象类型(如字典、列表、字符串等),或者自定义的类实例。但如果传入的参数不具有__dict__属性,那么就会出现上述的错误提示。 ### 回答2: “vars()”函数是Python内置的一个函数,用于返回一个对象的字典形式,包括对象的属性和值。当我们使用vars()函数时,参数必须是一个拥有__dict__属性的对象。 在Python中,每个对象都有一个字典形式的属性__dict__,存储了该对象的所有属性和对应的值。当我们调用vars()函数时,它会返回这个字典。 如果我们传递给vars()函数的参数不具备__dict__属性,就会出现错误信息“vars() argument must have __dict__ attribute”。 为什么要求参数具备__dict__属性呢?这是因为vars()函数的实现机制决定的。我们知道,vars()函数返回的是对象的属性和值,而这些属性和值都存储在对象的__dict__属性中。因此,只有具备__dict__属性的对象,才能正常的返回属性和值的字典形式。 举个例子,如果我们定义一个空的类,该类没有定义属性也没有实例化对象,那么这个类就没有__dict__属性,因为它没有任何属性需要存储。因此,如果我们尝试对这个类调用vars()函数,就会出现“vars() argument must have __dict__ attribute”的错误。 总结来说,vars()函数要求参数具有__dict__属性是因为它的实现机制需要读取对象的属性和值,并将其以字典形式返回。如果参数没有__dict__属性,就无法正常进行存储和读取操作,因此会报错。 ### 回答3: 当我们调用`vars()`函数时,我们必须给它传递一个具有`__dict__`属性的参数。`__dict__`属性是一个字典,它保存了对象的所有属性和对应的值。 这个错误通常发生在我们试图将一个不具备`__dict__`属性的对象作为参数传递给`vars()`函数时。这意味着该对象没有一个字典来保存其属性。例如,如果我们传递一个整数或一个函数作为参数,都会抛出这个错误。 正确的使用方法是,我们应该传递具有`__dict__`属性的对象给`vars()`函数。通常情况下,我们可以使用普通的自定义类的实例或内置的一些对象(如模块、类实例)作为`vars()`函数的参数。 要解决此错误,我们可以确保传递给`vars()`函数的对象具有`__dict__`属性。如果使用的是自定义类,可以在类定义中添加`__dict__`属性。对于一些内置的对象,我们可以直接使用。如果无法修改对象本身,我们可以考虑使用其他函数来获取对象的属性和值,例如`dir()`函数。这样我们就可以避免`vars()`调用时出现这个错误。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值