成员变量和局部变量
-
自定义的位置区别:
成员变量是定义在方法之外,类之内的变量。
局部变量是声明在方法之内的变量。
-
作用上的区别:
成员变量的作用描述一类事物的属性。
局部变量的作用是提供一个变量给方法内部使用的。
-
生命周期的区别;
- 成员变量随着对象的创建而存在,随着对象的消失而消失。
- 局部变量是调用到了对应的方法执行 到了创建该变量的语句时存在,一旦出了自己的作用域马上从内存中消失。
-
初始值的区别:
- 成员变量是有默认的初始值的。
- 局部变量是没有默认的初始值的,必须要先初始化才能使用。
构造函数
java构造函数函数详解
构造函数的作用: 给对应的对象进行初始化。
构造函数的定义的格式:
修饰符 函数名(形式参数){
函数体...
}
构造函数要注意的细节:
1. 构造函数 是没有返回值类型的。
2. 构造函数的函数名必须要与类名一致。
3. 构造函数并不是由我们手动调用的,而是在创建对应的对象时,jvm就会主动调用到对应的构造函数。
4. 如果一个类没有显式的写上一个构造方法时,那么java编译器会为该类添加一个无参的构造函数的。
5. 如果一个类已经显式的写上一个构造方法时,那么java编译器则 不会再为该类添加 一个无参 的构造方法。
6. 构造函数是 可以在一个类中以函数重载 的形式存在多个 的。
疑问:创建对象时,jvm就会调用到对应的构造方法,那么我们以前没有学构造方法,那么以前创建对象时,jvm是否 也会调用构造方法呢?如果有?构造方法从何而来呢?
会调用, java编译器在编译的 时候给加上去的。
构造函数与普通 函数的区别:
- 返回值类型的区别:
- 构造函数是没有返回值类型 的,
- 普通函数是有返回值类型的,即使函数没有返回值,返回值类型也要写上void。
- 函数名的区别:
- 构造函数的函数名必须要与类名一致,
- 普通函数的函数名只要符合标识符的命名规则即可。
- 调用方式的区别:
- 构造函数是 在创建对象的时候由jvm调用的。
- 普通函数是由我们使用对象调用的,一个对象可以对象多次普通 的函数,
- 作用上的区别:
- 构造函数 的作用用于初始化一个对象。
- 普通函数是用于描述一类事物的公共行为的。
//婴儿类
class Baby{
int id; //身份证
String name; //名字
//构造函数
public Baby(int i , String n){
id = i;
name = n;
System.out.println("baby的属性初始化完毕!!");
}
//无参 的构造函数
public Baby(){
System.out.println("无参的构造函数被调用了..");
}
//哭
public void cry(){
System.out.println(name+"哇哇哭...");
}
}
class Demo2
{
public static void main(String[] args)
{
//创建一个baby对象
Baby b1 = new Baby(110,"狗娃"); //婴儿诞生 白户
System.out.println("编号:"+ b1.id +" 姓名:"+ b1.name);
b1.cry();
b1.cry();
/* //黑户 Baby b2 = new Baby(); new Baby(); b2.id = 112; b2.name = "狗剩"; System.out.println("编号:"+ b2.id +" 姓名:"+ b2.name); */
}
}
iOS构造函数对比描述
1,概念
构造方法:指和类同名,用于构造对象(即生成对象)的方法;
实例方法:指的是在实例生成之后,实例调用的方法。
构造方法->构造实例;
实例产生->调用实例方法。
详细说来,就是类调用构造方法,来生成了一个实例,而这个实例产生了以后,才会调用实例方法来完成一些行为。
2,两者之间的差异
行为差异:构造方法,创建对象后自动调用构造方法;
实例方法,必须已经存在对象,并调用实例方法。
功能差异:构造方法多用于初始化对象状态,对属性赋初值;
实例方法用于实现某个功能
3,举例说明
构造方法分为系统自带和自定义构造方法。
(1)如果是系统自带的构造方法,需要重写父类中自带的构造方法 比如init
(2)如果是自定义构造方法:属于对象方法那么以 - 号开头,返回值一般为id类型,方法名一般以init开头
/***************父类 Person.h文件*************************/
#import <Foundation/Foundation.h>
@interface Person : NSObject
// @property 默认生成的成员变量为@private类型子类无法直接访问 可以通过get/set方法访问
// 年龄
@property int age;
// 姓名
@property NSString *name;
// 自定义构造方法 在初始化的时候为属性"年龄"和"姓名"赋值
- (id)initWithAge:(int)age andName:(NSString *)name;
@end
/*************父类 Person.m文件 *****************************/
#import "Person.h"
@implementation Person
// 重写父类的init方法 父类init方法返回的是id类型就是为了让任何子类的对象调用
- (id)init
{
// 1.首先初始化父类NSObject中声明的一些成员变量和属性 然后将初始化的对象赋值给当前对象
self = [super init];
// 2.如果父类的初始化成功 再初始化子类对象
if (self!= nil) { // self是个指针 如果为空意味着指向0 也可以这样写 self != 0
_age = 10;
}
// 3.返回已经初始化完毕的对象
return self;
}
// 实现自定义构造函数 在初始化的时候为属性赋值
- (id)initWithAge:(int)age andName:(NSString *)name
{
if (self = [super init]) {
_age = age;
_name = name;
}
return self;
}
@end
构造代码块
构造代码块的作用:给对象进行统一的初始化。
构造函数的作用: 给对应的对象进行初始化。
构造代码块的格式:
{
构造代码块
}
注意: 构造代码块的大括号必须位于成员 位置上。
代码块的类别:
- 构造代码块。
- 局部代码块. 大括号位于方法之内。 作用:缩短局部 变量 的生命周期,节省一点点内存。
- 静态代码块 static
class Baby{
int id; //身份证
String name; //名字
//构造代码块...
{
//System.out.println("构造代码块的代码执行了......");
}
//带参构造函数
public Baby(int i , String n){
id = i;
name = n;
}
//无参构造方法
public Baby(){
}
public void cry(){
System.out.println(name+"哇哇哭...");
}
}
class Demo4
{
public static void main(String[] args)
{
Baby b1 = new Baby(110,"狗娃"); // 狗娃 狗剩 铁蛋
System.out.println("编号:"+ b1.id + " 名字:"+b1.name);
/* System.out.println("编号:"+ b1.id + " 名字:"+b1.name); new Baby(112,"狗剩"); new Baby(); */
/* new Baby(110,"狗娃"); new Baby(112,"狗剩"); new Baby(); */
}
}
构造 代码块要注意的事项:
- java编译器编译一个java源文件的时候,会把成员变量的声明语句提前至一个类的最前端。
- 成员变量的初始化工作其实都在在构造函数中执行的。
- 一旦经过java编译器编译后,那么构造代码块的代码块就会被移动构造函数中执行,是在构造函数之前执行的,构造函数的中代码是最后执行 的。
- 成员变量的显示初始化与构造代码块 的代码是按照当前代码的顺序执行的。
this关键字 static关键字 静态函数
java中this关键字 static关键字 静态函数讲解
iOS中this的一些举例
static这个单词翻译成中文是“静态”的意思。关从字面上理解还真没法跟他的作用关联起来,下面我们直接先看他的作用:
- (1)修饰局部变量
保证局部变量永远只初始化一次,在程序的运行过程中永远只有一份内存, 生命周期类似全局变量了,但是作用域不变。这句话怎么理解呢?还是以代码例子来讲解吧。
随便建一个工程,在一个控制器类上监听控制器view的点击事件方法:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{ //声明一个局部变量i
int i = 0; //每次点击view来到这个方法时让i自增
i ++; //打印结果
NSLog(@"i=%d",i);
}
输出日志如下:
2016-10-26 14:58:48.290 fff[2760:170260] i=1
2016-10-26 14:58:49.044 fff[2760:170260] i=1
2016-10-26 14:58:49.200 fff[2760:170260] i=1....
从输出日志中我们可以看到i一直等于1,这也是预料之中的,因为每次点击进入这个方法就会重新初始化一个全新的变量i = 0,加加了一次后值变为1,然后打印出结果为1,出了这个方法后局部变量i就被释放回收。所以每次打印出来的结果都为1。
但是我们再看看局部变量i被关键字static修饰后的情况:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{ //声明一个局部变量i
static int i = 0; //每次点击view来到这个方法时让i自增
i ++; //打印结果
NSLog(@"i=%d",i);
}
输出日志如下:
2016-10-26 15:07:34.276 fff[2817:175155] i=1
2016-10-26 15:07:35.347 fff[2817:175155] i=2
2016-10-26 15:07:35.761 fff[2817:175155] i=3
2016-10-26 15:07:36.057 fff[2817:175155] i=4
2016-10-26 15:07:36.415 fff[2817:175155] i=5....
上面日志中可以看到i的值一直在自增。什么,它不是每次进去都被初始化赋值为0了么,怎么能累加呢。这就是关键字static修饰的局部变量的作用,让局部变量永远只初始化一次,一份内存,生命周期已经跟全局变量类似了,只是作用域不变。
- (2)修饰全局变量
使全局变量的作用域仅限于当前文件内部,即当前文件内部才能访问该全局变量。
iOS中在一个文件声明的全局变量,工程的其他文件也是能访问的,但是我又不想让其他文件访问,这时就可以用static修饰它了,比较典型的是使用GCD一次性函数创建的单例,全局变量基本上都会用static修饰。
下面是一个GCD一次函数创建的单利
@implementation LoginTool
//static修饰全局变量,让外界文件无法访问
static LoginTool *_sharedManager = nil;
+ (LoginTool *)sharedManager {
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedManager = [[self alloc] init];
});
return _sharedManager;
}
- (3)修饰函数
static修饰函数时,被修饰的函数被称为静态函数,使得外部文件无法访问这个函数,仅本文件可以访问。这个在oc语言开发中几乎很少用,c语言倒是能看到一些影子,所以不详细探讨。