第四周总结
一、static用于修饰类、字段、属性、方法以及构造方法等,被static修饰的成员为静态成员,静态成员包括静态字段、静态属性、静态方法、静态方法、静态构造方法注意静态类不是静态成员
4.8.1静态字段:静态字段是被static修饰的字段,它不属于任何对象,只属于类,而且只能通过“类名.静态字段名”的方式来访问。
使用方法:例如某个学校所有学生共享一个学校名称,此时完全不必在每个学生对象所占用的内存空间都定义一个字段来存储这个学校名称,此时可定义一个静态字段来表示学校名称让所有对象来共享。具体代码如下:
注意: 无论创建多少个Student对象,静态字段schoolName的值都不会改变,要想改变静态字段的值只有通过“类命.静态字段名”的方式并为其重新赋值,如:
Student.schoolName=“School“
这样Student类的静态字段值就变成了“school“
引用:“无论创建多少个Student对象,静态字段schoolName的值都不会改变“为什么不会改变?
答案是这样的,内存可以物理划分成五块堆、栈、静态存储区、程序代码区、文字区,不用说静态字段是存储在静态存储区,对象存储在程序代码区,所以无论创建多少个Student对象,静态字段schoolName的值都不会改变,注意:静态字段一旦被使用便会一直存在直到程序生命周期结束,所以静态成员很占用资源。
补充几个关于静态字段的问题:
静态字段与非静态字段的区别:
1、静态字段通过类名访问,非静态字段通多对象名访问
2、静态字段属于类,为所有对象所用,非静态字段属于对象,为对象专用;
3 静态字段用使用static修饰符来修饰,非静态不用;
静态属性:用static修饰的属性成为静态属性,调用方式同静态字段一样,
静态类总结:
1、 只要是静态成员,都要使用类名去调用,非静态成员都要使用对象名去调用
2、 静态函数中,只能访问静态成员,不能访问实例成员,实例函数中,既可以使用实例成员,也可以使用静态成员。
3、静态类中只能出现静态成员。
4.静态类不能创建对象,即不允许被实例化。
5.非静态类可以包含静态的方法字段、属性或事件,
6.无论对一个类创健多少个实例,它的静态成员都只有一个副本,
7.静态方法和属性不能访问其包含类型中的非静态字段和事件。
8.静态方法只能被重载,而不能被重写,因为静态方法不属于类的实例成员:
9.虽然字段不能声明为static const,但const字段的行为在本质上是静态的。这样的字段属于类,
不属于类的实例。因此,可以同对待静态字段样使用ClassName.MemberName表示法来访问const字段
10.静态字段属于类,井为类所用。而非静态字段属于对象,只能被特定的对象专有。
11.在跟类的实例无关,只跟类有关的情况下使用静态成员(如Math类的数学计算方法等不需要创建多个实例)
12.使用静态成员可以避免创建对象时引入一次对象的构造和一次对象的析构
13.注意,Connection连接对象不可使用static,静态化导致大最并发使用相同连核池,而连接池是有个数限制的,会导致数据库连接池达到最大值而不能继续访问网站。
静态类的主要特性:
1仅包含静态成员
2.无法实例化
3.是密封的
4.不能包含实例构造函数。
关于静态类问题补充:
什么时候使用静态类?
1.经常使用的类,即“工具类”
3、 需要存储全局可见的数据。
私有构造器与静态类的区别:
1) 私有构造器方式仍然可以从类的内部对类进行实例化,而静态类禁止从任何地方实例化类其中包括从类自身内部
2)在使用私有构造器的类中,是允许有实例成员的,而C# 2.0和更高版本的编译器不允许静态类有任何实例成员,
使用静态类的优点:
使用静态类的优点在于,编译器能够执行检查似确保不致偶然地添加实例成员,编译器将保证不会创建此类的实假静态类的另一个特征在于, C#编译器会自动方sealed这个关键字将类指定为不可扩展,换言之,不能从它派生出其他类。
3.静态方法只能访问静态成员,实例方法可以访问静态和实例成员么?
之所以不允许静态方法访问实例成员变量,是因为实例成员变量是属于某个对象的,
而静态方法在执行时,并不一定存在对象。同样,因为实例方法可以访问实例成员变量,
如果允许静态方法调用实例方法,将间接地允许它使用实例成员变量,所以它也不能调用实例方法。基于同样的道理,静态方法中也不能使用关键字this
main()方法是一个典型的静态方法,它同样遵循一般静态方法的规则,所以它可以由系统在创建对象之前就调用。
静态构造方法:静态构造方法的作用是初始化静态成员,一个类只能有一个静态构造方法,该静态构造方法没有任何修饰符,也没有参数可以被定义在静态类和非静态类中,注意静态构造方法会在程序创建第一个实例或引用任何静态成员之前,完成类中静态成员的初始化。
在使用静态构造函数的时候应该注意几点:
1、静态构造函数既没有访问修饰符,也没有参数。因为是.NET调用的,所以像public和private等修饰符就没有意义了。
2、是在创建第一个类实例或任何静态成员被引用时, .NET将自动调用静态构造函数来初始化类,也就是说我们无法直接调用静态构造函数,也就无法控制什么时候执行静态构造函数了。
3、一个类只能有一个静态构造函数。
4无参数的构造函数可以与静态构造函数共存。尽管参数列表相同,但一个属于类,一个属于实例,所以不会冲突。
5、最多只运行一次。
6.静态构造函数不可以被继承。
7.如果没有写静态构造函数,而类中包含带有初始值设定的静态成员,那么编译器会自动生成默认的静态构造函数。
单例模式:单例模式是c#中的一种设计模式,它是指在设计一个类时,需要保证整个程序在运行期间只存在一个实例对象。单例模式(Singleton)是几个创建模式中最对立的一个,它的主要特点不是根据用户程序调用生成一个新的实例,而是控制某个类型的实例唯一性,我们知道它包含的角色只有一个,就是Singleton,它拥有一个私有构造函数,这确保用户无法通过new直接实例它。除此之外,该模式中包含一个静态私有成员变量instance与静态公有方法Instance()。Instance()方法负责检验并实例化自己,然后存储在静态成员变量中,以确保只有一个实例被创建。作用:单例模式就是保证在整个应用程序的生命周期中,在任何时刻,被指定的类只有一个实例,并为客户程序提供一个获取该实例的全局访问点。
单例模式三种写法
1.经典模式:
public class Singleton
{ private static Singleton instance; private Singleton()
{
} public static Singleton GetInstance()
{ if(instance==null)
{
instance=new Singleton();
} return instance;
}
}
在这种经典模式下,没有考虑线程并发获取实例问题,即可能出现两个线程同时获取instance实例,且此时其为null时,就会出现两个线程分别创建了instance,违反了单例规则。因此,需对上面代码修改。
2 多线程下的单例模式
public class Singleton
{ private static Singleton instance; private static object _lock=new object(); private Singleton()
{
} public static Singleton GetInstance()
{ if(instance==null)
{ lock(_lock)
{ if(instance==null)
{
instance=new Singleton();
}
}
} return instance;
}
}
上述代码使用了双重锁方式较好地解决了多线程下的单例模式实现。先看内层的if语句块,使用这个语句块时,先进行加锁操作,保证只有一个线程可以访问该语句块,进而保证只创建了一个实例。再看外层的if语句块,这使得每个线程欲获取实例时不必每次都得加锁,因为只有实例为空时(即需要创建一个实例),才需加锁创建,若果已存在一个实例,就直接返回该实例,节省了性能开销。
3 饿汉模式
public sealed class Singleton
{ private static readonly Singleton instance=new Singleton(); private Singleton()
{
} public static Singleton GetInstance()
{ return instance;
}
}
上面使用的readonly关键可以跟static一起使用,用于指定该常量是类别级的,它的初始化交由静态构造函数实现,并可以在运行时编译。在这种模式下,无需自己解决线程安全性问题,CLR会给我们解决。由此可以看到这个类被加载时,会自动实例化这个类,而不用在第一次调用GetInstance()后才实例化出唯一的单例对象。
单例模式的优点
单例模式(Singleton)会控制其实例对象的数量,从而确保访问对象的唯一性。
实例控制:单例模式防止其它对象对自己的实例化,确保所有的对象都访问一个实例。
伸缩性:因为由类自己来控制实例化进程,类就在改变实例化进程上有相应的伸缩性。
单例模式的缺点:
系统开销。虽然这个系统开销看起来很小,但是每次引用这个类实例的时候都要进行实例是否存在的检查。这个问题可以通过静态实例来解决。
开发混淆。当使用一个单例模式的对象的时候(特别是定义在类库中的),开发人员必须要记住不能使用new关键字来实例化对象。因为开发者看不到在类库中的源代码,所以当他们发现不能实例化一个类的时候会很惊讶。
对象生命周期。单例模式没有提出对象的销毁。在提供内存管理的开发语言(比如,基于.NetFramework的语言)中,只有单例模式对象自己才能将对象实例销毁,因为只有它拥有对实例的引用。在各种开发语言中,比如C++,其它类可以销毁对象实例,但是这么做将导致单例类内部的指针指向不明。
单例适用性
使用Singleton模式有一个必要条件:在一个系统要求一个类只有一个实例时才应当使用单例模式。反之,如果一个类可以有几个实例共存,就不要使用单例模式。
不要使用单例模式存取全局变量。这违背了单例模式的用意,最好放到对应类的静态成员中。
不要将数据库连接做成单例,因为一个系统可能会与数据库有多个连接,并且在有连接池的情况下,应当尽可能及时释放连接。Singleton模式由于使用静态成员存储类实例,所以可能会造成资源无法及时释放,带来问题。
嵌套类:从作用域的角度看,嵌套类被隐藏在外围类之中,该类名只能在外围类中使用。如果在外围类的作用域内使用该类名时,需要加名字限定。从访问权限的角度来看,嵌套类名与它的外围类的对象成员名具有相同的访问权限规则。不能访问嵌套类的对象中的私有成员函数,也不能对外围类的私有部分中的嵌套类建立对象。嵌套类中说明的成员不是外围类中对象的成员,反之亦然。嵌套类的成员函数对外围类的成员没有访问权,反之亦然。国此,在分析嵌套类与外围类的成员访问关系时,往往把嵌套类看作非嵌套类来处理.
由引可见,嵌套类仅仅是语法上的嵌入。
嵌套类可以很好的适用于「需要一个辅助类来代替包含类工作的情形」。例如,容器类可能维护了一组对象,假设你需要一些工具来迭代这些被包含的对象,并允许执行迭代的外部用户维护一个代表迭代过程中当前位置的标记或迭代器——这可以改变容器类的内部行为而不会破坏使用容器类的代码,带来的巨大的灵活性。这个时候嵌套类就可以提供一个很好的解决方案。
匿名类:匿名类型的使用场景 当类中只定义了一些字段和属性,没有构造函数、方法、委托事件等比较复杂的成员,而且这个类的使用频率不高时,我们就可以使用匿名类型。2、匿名类型的定义 定义一个匿名类型时,需要使用var关键字和对象初始化语法。
var:编译器会在编译时自动生成新类的定义。
初始化:编译器会为类创建私有的字段和(只读)属性。
特点:
1. 只能包含公共变量
2.声明匿名类时必须初始化变量
3.无法使用静态变量
4.无法为匿名类定义类型
5.函数签名不指定变量类型;
对象初始化器:在一个类中,通常时使用构造方法来为属性赋值,当一个类中属性过多时,不可能为每种情况都创建一个构造方法,此时可以使用对象初始化器来为属性赋值,语法格式如下:
类名 变量名=new 类名(){属性名=值、属性名=值…..};
对象初始化器与构造方法的异同比较
相同点是:两者都可以完成对象属性的初始化
不同点是:
构造函数具有强制性,而对象初始化器没有强制性。
独享初始化只能完成属性初始化;而构造方法是写在类里面。
构造方法在.NET1.0就有。
对象初始化器在.NET3.0以上版本才有。
原文:https://www.cnblogs.com/LiangIT12138/p/10554869.html