字段的本质是变量,但与方法体当中的局部变量不同,后者是在方法运行时帮助方法暂时存储数据;而字段是用来为对象或类型存储数据的,那么,当一个对象或类型有多个字段时,这些字段的值就可组合起来表示该对象或类型的目前状态;
字段的英文单词是 “field” ,表示一块数据存放的空间
要求:每个学生都有其年龄和分数;整个班级有其平均年龄,平均分数和学生总数;假设,每个学生的分数是50加上各自的编号,每个学生年龄是20加上各自的编号;有100个学生,打印出平均分数和平均年龄;
字段的名字必须是名词(字段用以表达数据)
提醒:字段 (field) 是一种表示与对象或类关联的变量的成员,所以,当一个类声明字段时,一定要写在类体当中,不能写在方法体中
在声明一个字段时就对其进行显式的初始化实际上与在构造器中对其进行初始化是一样的
//声明字段时就对其进行显式的初始化
class Student
{
public int Age = 20;
}
//表示任何一个该类的实例被创建时,它的Age都会被设为20;
//效果与在类的构造器中进行初始化是一样的
class Student
{
public int Age;
public Student()
{
Age = 20;
}
}
即:初始化器什么时候对字段的值进行初始化?
静态构造器就是把 “public” 改为 "static"
//静态构造器
class Student
{
public static int Amount;
static Student()
{
Amount = 100;
}
}
//静态构造器只在运行环境加载该数据类型时被调用一次
被 Readonly 修饰的字段称为 “只读字段”,顾名思义,就是只能读取该字段的值,并不能修改它的值
所以,对于实例只读字段来说,只有一个机会去给它赋值,就是在声明该字段的时候直接跟一个初始化器初始化它的值(与在构造函数中初始化是一样的)
//比如一个学生的学号就很适合被写成只读字段
class Student
{
public readonly int ID;
public Student()
{
this.ID = int id
}
}
//在创建实例时就会被编译器提醒输入一个ID值
属性是字段的自然扩展,大多数情况下是字段的包装器,为了字段的值不被非法值污染,逐步由繁到简创建了现有的属性
//字段的值被非法值污染
Student stu1 = new Student(20);
Student stu2 = new Student(20);
Student stu3 = new Student(200);//手滑多输入一个0,字段值被污染
class Student
{
public int Age;
public Student(int age)
{
this.Age = age
}
}
(1)为了字段的值不被非法值污染,创建了Get()方法和Set()方法;
Get()方法用于获取字段的值;Set()方法用于设置字段的值;从而使得类或实例不能直接访问字段,而是需要调用这两种方法来达到获取或设置字段的值的目的
编程规范建议:当一个字段的修饰符由 “pubic” 变为 “private”(不能从外部直接访问),该字段命名方法变为驼峰法
为了不使程序崩溃,可在try语句中创建实例,用catch子句抓住异常,然后向用户传递异常消息
(2)但是Get(),Set()方法写起来确实有些冗长,所以微软创建了属性这个类型成员,实现了Get(),Set()方法的功能,但语言结构更简单,更清晰
属性的声明包括完整声明和简略声明,这两者的区别在于如何去写getter和setter
解释:在之前的Set()方法中,声明了 “value” 这个变量,用以接收实例中对字段设置的值;但是在属性中的setter却没有 “value” 这个变量的声明,这是因为微软已经为我们准备好了一个默认的变量,这个变量就是 value,变量名不能被修改;而且,value 是一个上下文关键字(指value这个单词在某个特定的代码上下文中是一个关键字,被高亮为蓝色),微软规定,在写setter访问器时,已经为我们准备好了一个叫 value 的关键字,它代表着传进来的由用户设置的值,当value出了setter这个范围,就不再是关键字
简略声明出来的属性在功能上与一个公有的字段是完全相同的,也就是说其值是不受保护的;属性的简略声明非常简单,代码简短,带有这种属性的类一般就是为了传递数据
(1)只读属性:没有setter
(2)不是只读属性,但是在 set 前加了 private,表示该属性的setter只能在当前类体中访问,不能在外界访问
属性比字段更优越的一个地方体现在:属性可以实时动态地把值计算出来
举例说明:大于16的人可以去工作
(1)索引器一般都是用在集合类型中,用在非集合类型中的情况是非常少见的
(2)对于初学者很少有机会去写索引器
常量隶属于类型,常量的声明与字段非常类似,只是需要const关键字来修饰;常量 (constant) 是表示常量值(即,可以在编译时计算的值)的类成员;常量值:在编译器编译这段代码时,会拿这个值把常量的标识符给替换掉,从而提高程序运行效率
//例如
Math.PI
Int.Maxvalue
//都是类的成员,当然也可以自定义
(1)常量:隶属于类型,没有 “实例常量”
(2)只读字段:只有一个机会去进行初始化,就是在声明时后跟一个初始化器进行初始化,等价于在构造器中对其进行初始化
(3)只读属性:向外暴露数据时,建议使用属性,而该属性的值又不能更改,所以编写只读属性;
对于对象,使用实例只读属性;对于类型,使用静态只读属性;而且要分清真正的只读属性和把setter隐藏起来的属性;
当使用静态只读属性时,会发现其功能与常量有一些重叠,但要注意:常量在编译时,编译器会拿常量的值代替标识符,而静态只读属性没有这个功能,因而使用常量性能比较高(常量是类成员)
(4)静态只读字段
常量的数据类型只能是基本的数据类型(int,double…),不能用类类型或自定义结构体类型作为常量的类型,这种情况下,就不能使用常量,必须使用静态只读字段
如何在声明一个字段时后跟一个初始化器对其进行初始化