objective -c初写

最近在自己学习iOS程序,这篇博文的内容是刚学习Objective-C时做的笔记,力图达到用最短的时间了解OC并使用OC。Objective-C是OS X 和 iOS平台上面的主要编程语言,它是C语言的超集,在C语言的基础上增加了面向对象的特性。

Note: 文中代码所使用的编辑工具是Xcode5

一些主要概念

  • 类(Class) :一个应用是由大量的相互关联的类组成的:包括框架类库(如Cocoa、Cocoa Touch等)中的类,还有程序员自定定义的类。一个类文件包含两部分:interface( .h文件)和implementation(.m文件),前者用来申明公开的属性和方法(严格地说,属性也是方法),后者实现前面声明的属性和方法。
  • 类别(Categories):在不更改某个Class的代码情况下可以使用类别对该类的功能进行扩展。扩展的代码可以放在单独的文件或者放在被扩展类的implementation部分(如果可以看到的话,框架中的类如NSString,程序员是看不到其实现部分的)
  • 协议(Protocols):协议类似于C#或Java语言的接口,用来声明一组相关的方法,这些方法可以被申明为可选的(optional)或是必须的 (required),如果一个类遵循了一个协议,可选的方法不是必须要实现的。另外,协议可以继承于另一个协议(通常都是继承于NSObject这个协议的)。
  • 块(Blocks) :这个东西和匿名函数很类似

定义类

在.h文件中声明类的名称、属性和方法,放在.h中的属性和方法都是公开的,能够在其他的导入(import)了该.h文件的类里使用。在.m文件中实现具体的代码,下面是一个类的定义:

  • Person.h文件:
 1 #import <Foundation/Foundation.h>
 2
 3 @interface Person : NSObject
 4
 5 @property (strong, nonatomic)NSString *name;
 6 @property NSInteger age;
 7
 8 - (void) work;
 9 - (void) workFor:(NSString*)companyName;
10 - (void) buy:(NSString*)something from:(NSString*)store at:(NSDate*)time;
11 + (NSString*) whoIsYourDad;
12
13 @end
  • Person.m文件:
#import "Person.h"

@implementation Person
{
     int instanceVar;
}

- (void) work
{
      NSLog(@"work work");
}

 - (void) workFor:(NSString*)companyName
{
      NSLog(@"I am working for %@", companyName);
}

- (void) buy:(NSString*)something from:(NSString*)store at:(NSDate*)time
{
      NSLog(@"I love shopping");
}

+ (NSString*) whoIsYourDad
{
      return @"I like WARIII";
}
@end

其中,person.h文件中声明了类名、属性名称和方法名称。person.m文件中实现了具体的代码。

Note: #import是一个预处理指令,所谓预处理是指编译器编译代码前先要把源文件处理一次,比如把Foundation/Foundation.h的内容包括进来,这样才能做下一步的编译工作。当要包含SDK中的类库时,使用尖括号,如:#import <Foundation/Foundation.h>;当要包含项目中自己写的.h文件时用引号,如:#import "Person.h"。用#include也可以达到同样的目标,但是不建议使用,据说是后者会把同一个.h包含多次,而前者只包含一次。

类的声明

类的申明部分放在Person.h文件中,以@interface开头,以@end结尾

@interface Person : NSObject
//code
@end

Person是类的名称,NSObject为父类名称,用冒号表示继承关系,Objective-C和C#、Java是一样的,不支持多继承。

实例变量

实例变量写在一对大括号内,如本例中的instanceVar就是实例变量:

@implementation Person
{
    int instanceVar;
}

Note:放置类变量的大括号谓语关键字@implementation@interface 下方,即可以在.h文件中,也可以在.m文件中,具体有什么区别,我也没研究,知道的仁兄请赐教我吧。

类名有讲究

Objective-C没有命名空间或包的概念,可以通过在类名前面加上前缀以达到区分彼此的作用,如NSString类的NS就是前缀,可能表示NeXTstep系统,熟悉乔布斯的人应该知道这段渊源。

属性

@property (strong, nonatomic)NSString *name;
@property NSInteger age

属性的声明语句写在关键字@interface下面,@end之前。关键字@property用 来申明属性,编译器会根据这个关键字自动生成一个实例变量_age以及相关的get和set方法。也可以手动完成这些工作,效果是一样的,需要注意的是: 在调用get和set方法时,get方法名称和属性名称一样,不需要get前缀,但set方法需要写set前缀,不过通常也不用调用这个两个方法,直接点 号.后面加属性名称就行了。

如果属性的数据类型是基本类型,如本例中的age属性,属性前不用加上星号(当然,加上也不错,加上的话就表示是一个指针形的变量),否则如果数据类型是对象型的就必须加上星号。

strongnonatomic关键字表明了属性的某些特征,其中 strong表示属性是强引用类型的,于strong相对应的是weak,表示弱应用类型。在Objective-C运行过程中,通过被一个被称为自动引用计数器(ARC)的技术手段监控,如果指向一个在堆内存中的对象的强引用数量为0时,系统自动释放这个对象所占据的内存,storngweak关键字用来表示强引用和弱引用。此外还有一些常用修饰属性的关键字,列表如下:

关键字 描述 是否默认
strong 强引用
weak 弱引用  
readonly 只读  
readwrite 可读可写
natomic 具有原子性、线程安全的
nonatomic 不具有原子性,非线程安全的,如果属性不会被多个线程访问,建议定义成nonatomic类型,这样执行效率高  
getter 强行指定属性对应的getter方法  
setter 强行指定属性对应的setter方法  

Note:如果指向一个对象的强引用的变量个数减少到0个时,系统自动收回它所占据的内存。如果一个变量不加strongweak修饰时,默认是strong型的。当出现如下情况时,需要使用weak关键字,对象A强引用了对象B,这是对象B如果要引用对象A的话只能用弱引用,因为如果A和B互相强引用,那么这两个对象就永运不会被从内存中清除,这是不合理的。另外,局部变量默认是强引用类型,使用关键字 __weak可定义弱引用类型的局部变量。

实例方法

- (void) work;
- (void) workFor:(NSString*)companyName;
- (void) buy:(NSString*)something from:(NSString*)store at:(NSDate*)time;

实例方法的声明以-开头,声明语句位于关键字@interface和关键字@end之间,和属性是一样的(属性本质上也是方法),以第二个方法为例:(void)表示返回值,workFor是方法的名称,(NSString*)表示参数的类型,companyName是参数,可以在方法体内访问。workFor方法在.h文件中申明并且在.m文件中实现。

Objective-C的方法命名格式以一种接近自然语言形式定义,如上述最后一个那样,它的方法名称是 buy:from:at需要注意的是:冒号也是方法名称的组成部分。Objective-C不存在重载方法的概念,比如如下三个方法是完全独立的方法,而不是重载方法:

实例方法的实现在.m文件中,请参考上面的Person.m文件。

-(void) init;
-(void) init:(NSStrng*);
-(void) init:(NSString*) with(int)parm;

其中比较特殊的是init方法,该方法继承至NSObjectNSObject中包含了很多实用的方法,程序员自定义的类最好继承于它)。如果需要在初始化类的时候做一些额外的操作(比如给变量赋默认值),可以重写init方法,或添加形如initXXX之类的方法(约定俗成的命名方式)像如下这样:

- (id)init
{
    self = [super init];
    if (self) {
        //code
    }
    return self;
}

- (id)initWithP:(id)p
{
    self = [super init];
    if (self) {
        //code
    }
    return self;
}

类方法

+ (NSString*) whoIsYourDad;

类方法和实例方法的区别是前缀是+,而非-。同样声明语句位于关键字@interface和关键字@end之间,具体实现在.m文件中,请参考上面的Persion.m文件。

使用类

初始化类

由于所有的类都继承于NSObject,可以使用NSObject中的两个方法来初始化类,下面的表达式用来实例化一个Person对象:

Person *person = [[Person alloc]init];

alloc方法用来分配内存,init方法用来做一些初始化操作,类似于于Java和C#的构造函数。

调用方法

很多资料里不叫“调用方法”而叫“发送消息”,这里统一叫“调用方法”。
调用方法的格式如下:

[类名 类方法名]; //方法没有参数
[类名 类方法名:参数...];//方法有参数
[实例名 实例方法名];//方法没有参数
[实例名 实例方法名:参数...];//方法有参数

Note:如果一个实例变量为空(nil),调用其方法不会报错,结果是do nothing。

属性是特殊的方法,所以也可以像上面那样调用,但是也可以像Java和C#那样使用点号.访问,如下面两种写法是等价的:

person.age = 50;
[person setAge:50];

var = person.age;
var = [person age];

Note 推荐使用.调用属性,看上去一目了然,不管用那种方式,前后统一还是很重要的

类别

使用类别可以对已经存在的类的行为进行扩展,类似于C#中的扩展类,下面的例子用来给NSString类增加方法:

  • NSString+NSStringAddition.h文件:
#import <Foundation/Foundation.h>

@interface NSString (NSStringAddition)

-(BOOL)islongerThan:(NSString*)str;

@end
  • NSString+NSStringAddition.m文件:
#import "NSString+NSStringAddition.h"

@implementation NSString (NSStringAddition)

 -(BOOL)islongerThan:(NSString*)str
{
    return [self length] > [str length];
}

@end

在main方法中测试:

#import <Foundation/Foundation.h>
#import "NSString+NSStringAddition.h"

int main(int argc, const char * argv[])
{
    @autoreleasepool
   {
         NSString *strS = @"abc";
         NSString *strL = @"abcd";
         BOOL result = [strL islongerThan:strS];
         if (result)
         {
             NSLog(@"you are long");
         }
    }
    return 0;
}

Note:大家在做测试的时候,用XCode创建项目,最后选择OS X->Applcation->Command Line Tool,这样运行的时候不会启动模拟器,速度快些。

另一种使用类别的方法是针对自己编写的可以看到源码的类进行扩展,在此情况下,无需新的.h和.m文件,只要在原来的类的 .m文件中开头部分加入扩展的方法,如扩展前面的Person类:

#import "Person.h"

@interface Person()

@property NSString* privatePro;

@end

@implementation Person
{
    int instanceVar;
}

- (void) work
{
    NSLog(@"work work");
}
- (void) workFor:(NSString*)companyName
{
     NSLog(@"I am working for %@", companyName);
}

- (void) buy:(NSString*)something from:(NSString*)store at:(NSDate*)time
{
     NSLog(@"I love shopping");
}

+ (NSString*) whoIsYourDad
{
     return @"I like WARIII";
}
@end

此例中增加了一个属性:privatePro。也可以增加方法,在“@implementation Person”和“@end”之间实现即可,和其他方法一样。在iOS开发中,ViewController通常使用这种扩展方法,将不对外公开的控件声明在扩展部分。

协议

协议相当于C#、Java中的接口。协议的声明在.h文件中,现声明一个协议如下:

#import <Foundation/Foundation.h>

@protocol FlyProtocal <NSObject>

@required

- (void)fly;
- (void)flyTo:(NSObject*)space;

@optional

+ (void)canGodFly;

@end

其中,@required下面的方法是遵循协议的类必须实现的,@optional下面的方法是可选的。可以看到,canGodFly方法是类方法,协议里不仅可以申明实例方法,类方法也是可以的。下面编写一个遵循协议FlyProtocalBird类:

  • Bird.h
#import <Foundation/Foundation.h>
#import "FlyProtocal.h"
@interface Bird : NSObject <FlyProtocal>

@end
  • Bird.m
#import "Bird.h"

@implementation Bird

- (void)fly
{
     NSLog(@"I can fly");
}

- (void)flyTo:(NSObject*)space
{
     NSLog(@"fly to %@", space);
}

+ (void)canGodFly
{
     NSLog(@"God can fly");
}
@end

观察Bird.h文件,在类名后加<协议名>即表示类遵循协议。观察Bird.m,三个接口中定义的方法已经被实现,其中flyflyTo是必须实现的,canGodFly是可选的。

下面编写测试类ProtocalTest:

  • ProtocalTest.h
#import <Foundation/Foundation.h>
#import "FlyProtocal.h"

@interface ProtocalTest : NSObject

@property id<FlyProtocal> delegate;
-(void)testFly;

@end
  • ProtocalTest.m
#import "ProtocalTest.h"

@implementation ProtocalTest

- (void)testFly
{
    [self.delegate fly];
    [self.delegate flyTo:@"BeiJing"];
}
@end

在ProtocalTest中定义了一个属性:@property id<FlyProtocal> delegate;,该属性可以赋值一个遵循了协议FlyProtocal的类的实例。testFly方法试图调用属性delegate所指向的对象的flyflyTo方法。现编辑main方法如下:

#import <Foundation/Foundation.h>
#import "ProtocalTest.h"
#import "Bird.h"

int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
         ProtocalTest *test = [[ProtocalTest alloc]init];
         test.delegate = [[Bird alloc]init];
         [test testFly];
    }
    return 0;
}

和C#、Java的不同是,协议不可以当成一个数据类型,上面的例子中 @property id<FlyProtocal> delegate;不可以写为:@property FlyProtocal delegate;

在实际开发中,很多控件的事件和数据源都是用协议来实现,某个ViewController如欲处理一个控件的某个事件,它可能要实现某个指定的协议里的方法,控件会回调这些方法。

Note: id 类型的变量可以指向任何对象,它本身已经是一个指针,因此无需加上*

块类似于C#、Java中的匿名函数,不用块使用其他旧的方法一样可以达到相同的效果,和C#、Java一样,块的使用可以使代码更紧凑、便于阅读,显得高大上。

定义块


-(void)method
{
    NSInteger methodVar = 1;
    ^{
        //code
    };
    NSInteger (^myBlock)(NSInteger, NSInteger) = ^(NSInteger p1, NSInteger p2)
    {
        //code
        return methodVar + p1 + p2;
    };
}

如例子所示,块的定义是这样的格式:

^(参数类型 参数名称, 参数类型 参数名称...){
    代码
};

申明一个块类型的变量是这样的格式:

返回值类型(^变量名称)(参数类型, 参数类型...);

块类型的变量即可申明为方法内部的局部变量,也可以声明为类变量。

块代码体内能够使用包含块的方法内部的变量,如本例子中块中使用了局部变量methodVar。需注意的是块中代码体只能使用methodVar,而不能改变methodVar的值,要想改变局部变量的值,需要在声明局部变量的时候加上关键字__block

使用块

块可以作为方法的参数传递,以汽车为例,汽车在启动前和启动后要加入一些行为,这个行为由驾驶员决定,如下为代码实例:

  • Car.h
#import <Foundation/Foundation.h>

@interface Car : NSObject

-(void)runWithAction:(void(^)(void))beforeRunBlock afterRun:(void(^)(void))afterRunBlock;

@end
  • Car.m

#import "Car.h"

@implementation Car

-(void)runWithAction:(void(^)(void))beforeRunBlock afterRun:(void(^)(void))afterRunBlock
{
    beforeRunBlock();
    NSLog(@"run");
    afterRunBlock();
}

@end

块作为方法参数时格式和声明一个块类型的变量类似,只是少了变量名称

Note: 如果参数传来的是空(nil),执行 beforeRunBlock()会导致程序崩溃。

写一个Dirvier类如下:

  • Dirver.h
#import <Foundation/Foundation.h>
@interface Dirver : NSObject
- (void)drive;
@end
  • Dirver.m
#import "Dirver.h"
#import "Car.h"

@implementation Dirver

- (void)drive
{
    Car *car = [[Car alloc]init];

    void (^beforeRun)(void) = ^{
        NSLog(@"check tire");
    };

    void (^afterRun)(void) = ^{
        NSLog(@"close door");
    };

    [car runWithAction:beforeRun afterRun:afterRun];
}
@end

main方法:

#import <Foundation/Foundation.h>
#import "Dirver.h"
int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
        Dirver *dirver = [[Dirver alloc]init];
        [dirver drive];
    }
    return 0;
}

运行结果如下:

2014-03-21 13:57:48.037 BlockTest[1211:303] check tire
2014-03-21 13:57:48.039 BlockTest[1211:303] run
2014-03-21 13:57:48.040 BlockTest[1211:303] close door

Driver类中可以不定义块变量,以一种类似于匿名方法的书写格式书写:

#import "Dirver.h"
#import "Car.h"
@implementation Dirver
- (void)drive
{
    Car *car = [[Car alloc]init];
    [car runWithAction:^{
        NSLog(@"check tire");
    } afterRun:^{
        NSLog(@"close door");
    }];
}
@end

回调

处理事件离不开回调,下面介绍Objective-C的三种回调模式。

arget-action模式

target指某个对象,action指对象的行为,即某个方法,合起来就是回调某个对象的某个方法,关键字@selector用来得到方法名称的唯一标识,记作SEL。请看例子。

  • Car.h

#import <Foundation/Foundation.h>

@interface Car : NSObject

-(void) runWithAciton:(id)target selector:(SEL)oneSelector;

@end
  • Car.h
#import "Car.h"
@implementation Car
-(void) runWithAciton:(id)target selector:(SEL)oneSelector;
{
    if ([target respondsToSelector:oneSelector])
    {
        [target performSelector:oneSelector];
    }
    NSLog(@"run");
}
@end

场景:调用汽车跑起来前,要做一些额外的工作,这个工作将通过回调对象target中的方法oneSelector来完成。下面的代码将指定target和action:

  • test.h
#import <Foundation/Foundation.h>

@interface Test : NSObject

- (void)driver;

@end
  • test.m

#import "Test.h"
#import "Car.h"

@implementation Test

- (void)driver
{
    Car *car = [[Car alloc]init];
    [car runWithAciton:self selector:@selector(doSomeThing)];
}

- (void)doSomeThing
{
    NSLog(@"check tire before running");
}

@end

在main函数中测试:

#import <Foundation/Foundation.h>
#import "Test.h"

int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
        Test *test = [[Test alloc]init];
        [test driver];
    }
    return 0;
}

结果是:

2014-03-20 14:28:16.309 TELTest[1531:303] check tire before running
2014-03-20 14:28:16.311 TELTest[1531:303] run

协议模式

场景:在汽车跑起来前已经跑起来后需要做一些额外的工作,并且在某些情况下可以制止汽车跑起来(比如前方睡着一只猫的时候),下面将这三个行为封装在一个协议中:

#import <Foundation/Foundation.h>

@protocol CarDelegate <NSObject>

-(BOOL)shouldCarRun;
-(void)didBeforeCarRun;
-(void)didAfterCarRun;

@end

在Car类中,增加代码如下:

  • Car.h
#import <Foundation/Foundation.h>
#import "CarDelegate.h"

@interface Car : NSObject

@property id<CarDelegate> delegate;
-(void) run;
-(void) runWithAciton:(id)target selector:(SEL)oneSelector;

@end
  • Car.m
#import "Car.h"

@implementation Car

-(void) runWithAciton:(id)target selector:(SEL)oneSelector;
{
    if ([target respondsToSelector:oneSelector])
    {
        [target performSelector:oneSelector];
    }
    NSLog(@"run");
}

-(void) run
{
    if (![self.delegate shouldCarRun])
    {
        return;
    }
    [self.delegate didBeforeCarRun];
    NSLog(@"run");
    [self.delegate didAfterCarRun];
}
@end

修改Test类,使其遵循协议CarDelegate:

  • Test.h
#import <Foundation/Foundation.h>
#import "CarDelegate.h"

@interface Test : NSObject<CarDelegate>

- (void)driver;

@end
  • Test.m
#import "Test.h"
#import "Car.h"

@implementation Test

- (void)driver
{
    Car *car = [[Car alloc]init];
    car.delegate = self;
    [car run];
}

-(BOOL)shouldCarRun
{
    //NSLog(@"the cat is sleeping");
    //return NO;
    return YES;
}

-(void)didBeforeCarRun
{
    NSLog(@"check tire before running");
}

-(void)didAfterCarRun
{
    NSLog(@"close the door");
}

@end

再次运行main函数:

2014-03-20 15:08:03.517 TELTest[1709:303] check tire before running
2014-03-20 15:08:03.520 TELTest[1709:303] run
2014-03-20 15:08:03.521 TELTest[1709:303] close the door

消息中心模式

注册观察者到消息中心,消息中心发送消息给注册者,并回调注册者的方法。下面是一个观察者的例子:

  • Observer.h
#import <Foundation/Foundation.h>

@interface Observer : NSObject

@end
  • Observer.m
#import "Observer.h"

@implementation Observer

-(id)init
{
    self = [super init];
    if (self)
    {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doSomething:) name:@"TestNotification" object:nil];
    }
    return self;
}

- (void)doSomething:(NSNotification*) aNotification
{
    NSString *message = (NSString*)aNotification.object;
    NSLog(@"the message is %@", message);
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end

在main方法中编写测试代码:

#import <Foundation/Foundation.h>
#import "Observer.h"

int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
         __unused Observer *observer = [[Observer alloc]init];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"TestNotification" object:@"hello world"];
    }
    return 0;
}

运行结果如下:
2014-10-10 16:12:32.017 ObserverTest[1888:303] the message is hello world

时间: 2024-11-13 11:15:30

objective -c初写的相关文章

初写接口的的代码经验总结

初写接口的代码要精简,就要注意以下几点: 1.接口的输入数据格式判断是否满足要求:应使用Try Catch判断输入的格式是否正确,不正确应进行相应的提醒. 2.输入数据格式的转换:.输入数据的格式要转换为最适合算法处理的格式,比如,输入的字符串类型为"yyyy/MM/dd HH:mm:ss",此为时间格式应转换为Calendar类,以便处理. 3.算法的主函数应为Public权限,主函数也就是主算法,其中包含的子算法应模块化,权限为Private,在类内部互相调用.

刚搭建的linux环境的基本优化以及优化脚本---菜鸟初写

本篇博文主要是参考并借鉴老男孩老师的优秀博文外加自己总结及写的优化脚本!博文地址:http://oldboy.blog.51cto.com/2561410/1336488 虽然我并没有参加过老男孩老师的培训但是看过他的优秀视频和优秀博文,接受过他的熏陶与教育,在这里十分感谢老男孩老师!!! 还有这篇博文之中一些操作与脚本的编写非常感谢京峰老师们的帮助! 主要优化的目录 我使用的linux版本是CentOS6.6 x86_64 1.网络配置优化 2.关闭selinux及清除iptables链 3.

枚举:enum——初写

入门的时候,针对某一字段状态的判断,一开始是在前端用if else 判断,有一些弊端:①把内置的code暴露给用户②if else最好不要超过3层③前端很长一段冗余判断不规范后改进使用枚举,在后台进行处理,将代码整理如下: (凑字数,忽略...这是一个初夏的季节,今天早上不想起床7:40的闹钟,平时是7:30,然后,用了二十几分钟的时间洗漱,化妆(淡妆)背着电脑出门了,天气有点炎热,路过卖早餐的地方,一点胃口都没有,因为喜欢幻想,幻想一下更恶心了,哈哈哈...夏天是个发瘦的季节(*^__^*)

nodejs初写心得

nodejs安装后如何查看和安装其他工具 网上nodejs的文章已经很多,这里只是写下自己的小小心得,如果能帮到别人当然更好. 安装nodejs这里就不叙述了,直接上nodejs官网下载就好了,初学者建议直接下载安装版,无需自己去编译.nodejs安装版和安装其他软件一样,无门槛. nodejs 0.6.0之后的版本已经可用在windows下面运行,且自带 npm 包安装管理器. 安装nodejs后启动node.js,会打开一个类似黑色的系统命令框,这里是直接输入js代码的命令框,因此在这里输入

php初写成

学习php差不多了,最近主要学习ThinkPHP框架,记录几个要点 1.在php配置里面打开extension=php_pdo_odbc.dll这个库,以便于使用重写url. 2.在config.php文件里面配置数据库信息. 3.页面的跳转是个令人头疼的问题,一般用success()函数都会成功.而同一个文件夹里面的html文件里的直接用U()就行了. 4.自己做了个构造函数,让其他控制器都加载这个函数,达到验证用户cookie的作用. 5.自己做了个cookie,逻辑就是,用户登录成功后开始

SpringMVC初写(二)映射类型、限制和数据绑定

映射路径 a)映射路径的概述 所谓的映射路径,就是匹配请求路径和执行方法关系的路径 请求路径:http://localhost:8080/springmvc-demo-cofig/say.do 映射路径:@RequestMapping(value=“/say.do”) 基于注解的映射路径可以忽略前后缀 例:@RequestMapping(value=“/say.do”)与下面三种表达式相同 [email protected](value="say.do") [email protect

SpringMVC初写(四)上传和下载功能的实现

一.文件上传 流程: 导入包commons-fileuplad组件和依赖包commons-io组件 配置springmvc支持上传的组件: 启动SpringMVC注解支持 配置上传解释器 构建一个上传表单 在业务控制器Controller中编写上传文件的处理方法代码 导入需要的的包 配置SpringMVC配置文件 注:因为在SpringMVC核心控制器DispacherServlet源码中,multipartResolver是一个固定加载属性,因此配置的上传解释器名字必须是multipartRe

第一个MyBatis程序(博客初写者)

第一个Mybatis程序 一.环境: 1.JDK1.8 2.MYSQL5.7 3.IDEA 4.MAVEN 3.63 二.Mybatis认识: 1.查看官方文档 https://mybatis.org/mybatis-3/zh/index.html 2.查看百度百科 https://baike.so.com/doc/5582692-5795562.html MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设

PHP写时复制

原文:http://www.huamanshu.com/blog/2014-05-18.html 起源 写时复制英文名字叫“copy-on-write”,简称“cow”,又名“靠” 今天查了下这个"cow",原来起源于*nix内存管理机制,后来广泛应用在其它开发语言上,C++的STL,还有PHP,相信很多人都了解这个写时复制,经常跟别人侃得甚欢. $foo = 'foo'; $bar = $foo; 不会 初写这样的PHP代码时,常会问,这样的话会不会因为复制而占用更多内存,旁边会有人