java泛型详解是什么?不要复制百科上的,谢谢。

韩国综艺节目的“文化冲击”是什么意思?(最好不要复制一大堆百科上的东西,谢谢合作)_百度知道
韩国综艺节目的“文化冲击”是什么意思?(最好不要复制一大堆百科上的东西,谢谢合作)
您的回答被采纳后将获得:
系统奖励20(财富值+经验值)+难题奖励20(财富值+经验值)
我有更好的答案
每个国家都有属于自己的文化底蕴,像咱们中国就是中庸之道,文化冲击就是指一些事件一句话,不符合一个国家大部分大众的文化习惯,
其他类似问题
为您推荐:
韩国综艺节目的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁一、桃花眼的特点是什么?不要百度百科的答案复制。二、请发几张桃花眼代表人物的照片,谢谢_百度知道
一、桃花眼的特点是什么?不要百度百科的答案复制。二、请发几张桃花眼代表人物的照片,谢谢
我有更好的答案
恩黄子韬那样的吧
就你叶一茜那样的吧
景甜那样的吧
围观、、、、、、、、、、、、、、、、
其他类似问题
为您推荐:
桃花眼的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁& & “让错误尽量在编译被发现”& & “你必须知道边界所在,才能成为高手”& & ---《Thinking in Java》& & 错误在编译时被发现是十分让人向往的,Java泛型在JDK1.5中的引入目的就是“让编译器承担更多的工作,保证类型的正确”。但是随之而来的是开发社区褒贬不一的观点,就像在异常中说的那样----Java的泛型和异常一样,备受人们争议。& & Java泛型带来的优秀产物就是集合框架,相比于以前使用Java集合框架,使用泛型后的集合框架显得十分简洁和安全。随之而来的便是Java泛型给人们带来的种种疑惑,设计者曾说Java泛型的主要设计灵感是来自C++的模板,但是稍微知道C++的人也许都会对Java的泛型感到失望,如何优雅地使用Java泛型进行优秀的程序设计是值得探索的。& & 1.Java的泛型为什么会这样?& & Java的泛型是在Java出现几乎10年后才出现的特性,而此时已经存在大量的旧代码,作为一门广泛使用的生产语言,Java不得不考虑兼容性。为了让使用新特性的人能够逐步的迁移到新的平台,新代码必须和旧代码保持兼容,这是一个十分伟大的动机,不会在一夜之间破坏现有的所有代码!所以Java的设计者们在一个月黑风高的晚上决定使用“擦除机制”来设计泛型!& & 2.擦除机制& & 正确理解泛型概念的首要前提是理解擦除机制(type erasure)。Java中的泛型基本上都在编译器这个层次上来实现的。在生成的Java字节代码中是不包含泛型中的类型信息(在运行时时候都是原生类型(raw type))。在编写泛型代码的时的任何类型信息都会被编译器在编译的时候去掉。这个过程称为“类型擦除”。在代码中如:List与List等,在编译之后都会变成List。JVM看到的只是List,而由泛型附加的类型信息对JVM来说是不可见的(术语:不可具体化)。& & 擦除的整个过程也比较容易理解:首先找到用来替换类型参数的具体类。这个具体类不指名则默认Object,如果指定了参数类型的上界,那么就使用这个上界来替换类型参数。同时去掉类型声明,即去掉的内容,比如T get()方法声明就编程了Object get(),List就变成了List。接下来有时候可能会生成一些桥接方法。& & 3.不可具体化的类型& & 不可具体化的类型是指:运行时表示法包含的信息比它的编译时表示法包含的信息更少的类型。泛型是典型的不可具体化类型,参考ArrayList中放入取出对象时候的源代码& & public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] =
} public E get(int index) {
rangeCheck(index);
return elementData(index);
} @SuppressWarnings("unchecked")
EelementData(int index) {
return (E) elementData[index];
}& & 运行时实际持有Object数组,但是编译的时候是可以有效的判断放入的是否是String类型,从而避免ClassCastException异常。& & 与之相反的便是”可具体化的类型“,数组便是一个例子。数组总是在运行时才检查他们元素的类型约束。比如& & Object[]father = new Father[10];
father[0]= new Son();
father[1]= new Integer(100);& & 这里并没有编译错误,但是运行时会抛出ArrayStoreException异常,和泛型的特点相反。比如如下大家熟悉的代码:& & List&Object&list = new ArrayList&Long&();& & 这段代码是非法的。& & 更加让人感到疑惑的是如下的代码:& & Father[]father = new Son[10];
father[0]= new Son();
father[1]= new Father();& & 这段代码会在第三行抛出ArrayStoreException异常,是的,数组的类型是强制约束。按理来说,一个数组中放置的元素应该都是安全的,父类的数组是可以放置子类型的元素。子类的数组是可以向父类数组转型成功的(这里确实也转型成功了),但是运行时却抛出异常,最终原因就是实际运行的时候数组并不是Father类型,而是Son类型。这里的可具体化和泛型的不可具体化就产生了矛盾(如果你new了一个T并将其转型为Object类型,那么是可以放入任何类型的,编译时期是不能被编译器发现,但是运行时会很有可能会抛出ArrayStroeException或者是ClassCastException异常),于是又是一个月黑风高的晚上,Java的设计者们决定了另外一个一不做二不休的决定-----不能创建泛型数组。& & 在Java中你不能new T[],也不能通过如这样看似合理的ArrayListasd = new ArrayList[]; 代码,因为我是可以将其转型为Object[]类型,然后便可以向其中放入任何类型的类型了,而运行使JVM却对你说了NO,这对Java泛型就是一种赤裸裸的嘲讽!& & 4.通配符& & 泛型的通配符让Java的泛型变得更加的灵活和强大(虽然并不是那么强大)。参数化类型是不可变的,也就是说下面这样的代码是不能通过编译的:& & List&Object&f = new ArrayList&&();
List&String&f1 = new ArrayList&&();
f= f1;& & 第三行会报错!看似f1应该是f的子类,但是与直觉相悖。原因还是在”擦除“,由于List中的类都是被Object替代,而List中均被String替换,这里面如何来协调就是一个问题。& & 如果想写出更加强大的API,那么通配符就是你应该选择的。如下代码:& & public class Seven {
publicstatic void main(String[] args) throws InstantiationException, IllegalAccessException{
Stack&Number&stack = new Stack&&();
List&Integer&list = new ArrayList&&();
list.add(10);
list.add(100);
list.add(1000);
Iterable&Integer&iter =
stack.pushAll(iter);
}}class Stack&E&{
publicvoid push(E e){
* 这里是有通配符来提高API的灵活性
* @param i
publicvoid pushAll(Iterable&? extends E&i){
}}& & 其中Stack类在创建实例的时候使用了Number类型作为其类型参数,那么在创建pushAll这个方法的时候,如果使用pushAll(Iterablei)来作为签名,由于类型擦除机制,Java将在编译这一层面上对你SayNo!这里就引出PECS原则,即:如果参数化类型表示一个T生产者(Producer),就使用,如果它是一个T的消费者(Comsumer),则使用。这一点对于设计出优秀强大的泛型代码是一个不错的原则!& & 这里需要说明一下任意通配符----?,初看起来好像?和Object的区别不大(实际情况也是会被擦除为Object),但是如果你List,那么将不可以插入任何值(除了null,但是这个没有什么意义)。这里的?是告诉编译器,我不知道将会接受什么类型,但是请使用Java泛型机制来处理它!但是,实际上有多大,只有合适的情况才能发挥它的才能了。& & 与之相关的便是----类型捕获,参考下面的代码:& & //这里是有任意通配符,函数调用后随即捕获了?的类型信息
publicstatic void swap(List&?&list,int i,int j){
swapHelper(list,i, j);
//这里在由于helper知道E的类型,所以可以列表时安全的
privatestatic&T&void swapHelper(List&T&list,int i,int j){
list.set(i,list.set(j, list.get(i)));
}& & Java通配符确实对Java的泛型的强壮起到了十分关键的作用,如何优雅的使用通配符,除了牢记上面的PECS原则,更加需要经验和眼光!& & 5.其他的一些忠告& & 1.不要再新代码中使用原生类型& & Java就是为了兼容才将泛型做成目前的状况,以后也不会再出现使用原生类型的代
码,最最重要的是:Java的泛型出现的一点原因是消除原生态可能产生的
ClassCastException异常,实现安全,如果你使用了原生,你就浪费了Java对你的一片心
意。& & 但是有些地方必须使用原生类型:& & 1.类文字& & 2.静态方法或者域的使用& & 2.消除警告& & Java对你的代码进行警告,表示这个代码是有可能出现问题,代码中警告越多,出现问题的可能性越大,想到解决警告的办法是最好,如果无法消除,那么可以使用注解@SuppressWarnings来消除,但是必须在那里证明自己消除的警告是类型安全的,是实际不会出现问题的。& & 对于@SuppressWarnings应该在尽可能小的范围内使用,千万别误将范围扩大而消
除了本来十分危险的警告。另外需要注意的一点:@SuppressWarnings是不能被注解在
return语句之上的。& & 3.类表有限于数组& & 数组是在运行时确定信息,更容易出现问题,相对于类型安全的列表来说,有时候 牺牲一点性能而换来更多的安全和方便也是一个不错的选择。& & 4.优先考虑泛型& & 泛型代码的好处之一就是模板,代码可复用,这正是设计者们所追求的,但是只有在有充分的理由(代码能够跨越多个类进行工作时)来使用泛型,否则不要使用泛型!
相对于泛型类,优先使用泛型方法则显得更加的灵活。& & 5.优先考虑类型安全的异构容器& & 核心思想就是:将键(key)参数化而不是将容器参数化。& & 如下代码实现Map存放不同的key类型& & publicclass Eight {
publicstatic void main(String[] args) {
YiGouRongQiy = new YiGouRongQi();
y.put(String.class,"leon");
y.put(Integer.class,20);
System.out.println(y.get(String.class)+ " is " + y.get(Integer.class) + " years old!");
}} class YiGouRongQi{
privateMap&Class&?&,Object&hm = new HashMap&&();
public&T&boolean put(Class&?&type,T instance){
if(type== null){
System.out.println("空指针异常");
elseif(hm.containsKey(type)){
System.out.println("已经存在了键");
hm.put(type,instance);
@SuppressWarnings("unchecked")
public&T&T get(Class&T&type){
//返回语句不能加注解//
return(T)hm.get(type);
returntype.cast(hm.get(type));
}}& & 集合API说明了泛型的一般应发,限制你每个容器只能有固定数目的类型参数。这 里展示了你可以将类型参数放在键上而不是容器上来避开这一限制。对于这种类型安全的异构容器,你可以使用Class对象作为键。& & 6.泛型的反思& & 经常提起Java泛型,人们大多数时候总是在提它的诟病,暂且搁置开Java的历史原因,说说到底什么是泛型。就像C++中泛型又被称为模板,是的,泛型是对普通方法更加泛化的实现,这种泛型类是适用于所有类或者部分类,一般情况下是使用与部分类。对这些类会存在某些限制,而泛型类并不关心类的具体类型是什么,而在乎它是否可以执行某个方法!& & 这便是“潜在的类型机制”。所以,一般泛型类会要求参数类型实现了某个方法或者存在某个方法,使用实现接口或者反射式完全可以反映泛型的特点,也就是说实现“类型潜在机制”。泛型,泛型,其内部本来就不应该保存类的具体信息,因为一旦是针对某个具体类进行泛型类的编写,那么这个泛型类就完全没有必要写出泛型类。所以说,虽然Java泛型机制给开发者带来了诸多的不便,比较遗憾的一点是没有支持泛型数组,但是反过来看,擦除内部参数类型信息,利用接口和反射实现潜在类型机制,到也不失为一种还算优雅的方式。& & 简单代码如下:& & public class Four {
publicstatic void main(String[] args) {
//客户类,调用泛型方法,传入实现规定接口的类
GenericTest.doIt(newTestClass());
System.out.println("------------------------------");
GenericTest.doIt(newTestClass2());
}}interface testInterface {
* 这个接口规定了需要做什么事情
publicvoid doSomething();} /** * 以下两个类是使用了接口的特点,针对接口进行编程 要实现泛型的潜在类型机制----“我不关心这里使用的类型,只要它具有这些方法即可” * 也可以使用反射进行实现,不需要依赖接口的方式 *@author leon * */class TestClass implements testInterface {
publicvoid doSomething() {
System.out.println("I'mLeon,I'll do some thing here!");
}} class TestClass2 implements testInterface {
publicvoid doSomething() {
System.out.println("I'mDiana,I'll do other thing here!");
}} class GenericTest {
* 这个泛型类中的泛型需要执行某些方法,但是必须 是实现了testInterface接口
* @param t
static&T extends testInterface&void doIt(T t) { //
//一旦T确定了,那么编译器便可以确定在类中或者方法中使用的类型的内部一致性//
//换句话说,就是这个类所有的T都被编译前替换了
System.out.println("Dobefore!");
t.doSomething();
System.out.println("Doafter!");
}}& & 7.类型系统& & 在Java中,大家比较熟悉的是通过继承机制而产生的类型体系结构。比如String继承& & 自Object。根据Liskov替换原则,子类是可以替换父类的。当需要Object类的引用的& & 时候,如果传入一个String对象是没有任何问题的。但是反过来的话,即用父类的引& & 用替换子类引用的时候,就需要进行强制类型转换。编译器并不能保证运行时刻这& & 种转换一定是合法的。这种自动的子类替换父类的类型转换机制,对于数组也是适& & 用的。String[]可以替换Object[]。但是泛型的引入,对于这个类型系统产生了一定的& & 影响。正如前面提到的List是不能替换掉List的。& & 引入泛型之后的类型系统增加了两个维度:一个是类型参数自身的继承体系结构,& & 另外一个是泛型类或接口自身的继承体系结构。第一个指的是对于 List和& & List这样的情况,类型参数String是继承自Object 的。而第二种指的是 List& & 接口继承自Collection 接口。对于这个类型系统,有如下的一些规则:& & 1.相同类型 参数的泛型类的关系取决于泛型类自身的继承体系结构。即& & List是Collection的子类型, List可以替换& & Collection。这种情况也适用于带有上下界的类型声明。& & 2.当泛型类的类型声明中使用了通配符的时候,其子类型可以在两个维度上分别& & 展开。如对Collection来说,其子类型可以在Collection 这个& & 维度上展开,即List和Set等;也可以在& & Number 这个层次上展开,即Collection和Collection等。如此& & 循环下去,ArrayList和HashSet等也都算是Collection<?extends& & Number>的子类型。& & 3.如果泛型类中包含多个类型参数,则对于每个类型参数分别应用上面的规则。& & 理解了上面的规则之后,就可以很容易的修正实例分析中给出的代码了。只需要把& & List改成List即可。List是List的子类型,因此传递参数时不会& & 发生错误。& & 注:上面这一点引用自《java深度历险》8.闲话& & Java的泛型已经是Java本身不可分割的一部分了,就像其异常,在未来改动的可能性十分的渺茫,在历史问题上面编写代码更多的时候需要更多的思考,Java的泛型在JDK中的主要应用就是集合框架,而事实证明集合框架确实不错,虽然Java中的泛型没有想象的那么强大。所以,泛型与异常一样,如何写出优雅的泛型是&#20540;得追求的艺术。
声明:该文章系网友上传分享,此内容仅代表网友个人经验或观点,不代表本网站立场和观点;若未进行原创声明,则表明该文章系转载自互联网;若该文章内容涉嫌侵权,请及时向
上一篇:下一篇:
相关经验教程
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.002 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益什么是泛型
一种类型占位符,或称之为类型参数。我们知道在一个方法中,一个变量的值可以作为参数,但其实这个变量的类型本身也可以作为参数。泛型允许我们在调用的时候再指定这个类型参数是什么。在.net中,泛型能够给我们带来的两个明显好处是&&类型安全和减少装箱、拆箱。
类型安全和装箱、拆箱
作为一种类型参数,泛型很容易给我们带来类型安全。而在以前,在.net1.1中我们要实现类型安全可以这样做 :
//假设你有一个人员集合
public class Person{
 private string _
 public string Name
 { get { return _ }
 set { _name =}}
//假设你有一个人员集合
public class PersonCollection : IList
 private ArrayList _Persons = new ArrayList();
 public Person this[int index]
 { get { return (Person)_Persons[index]; } }
 public int Add(Person item)
 { _Persons.Add(item);
  return _Persons.Count - 1;}
 public void Remove(Person item)
 { _Persons.Remove(item); }
 object IList.this[int index]
 { get { return _Persons[index]; }
 set { _Persons[index] = (Person) }}
 int IList.Add(object item)
 { return Add((Person)item); }
 void IList.Remove(object item)
 { Remove((Person)item); }
上述代码主要采用了显性接口成员(explicit interface member implementation)技术,能够实现类型安全,但问题是:
&产生重复代码。假设你还有一个Dog类集合,其功能相同,但为了类型安全,你必须要Copy一份代码,这样便使程序重复代码增加,当面对变化的时候,更难维护。
public class DogCollection : IList
 private ArrayList _Dogs = new ArrayList();
 public Dog this[int index]
 { get { return (Dog)_Dogs[index]; } }
 public int Add(Dog item)
 { _Dogs.Add(item);
  return _Dogs.Count - 1;}
 public void Remove(Dog item)
 { _Dogs.Remove(item); }
 object IList.this[int index]
 { get { return _Dogs[index]; }
 set { _Dogs[index] = (Dog) }}
 int IList.Add(object item)
 { return Add((Dog)item); }
 void IList.Remove(object item)
 { Remove((Dog)item); }
如果在泛型中,要实现类型安全,你不需要拷贝任何代码,你仅仅需要这样做:
List persons = new List();
persons.Add(new Person());
Person person = persons[0];
List dogs = new List();
dogs.Add(new Dog());
Dog dog = dogs[0];
&对于值类型的对象还是需要额外的装箱、拆箱。其实对于传统的集合来说,只要其中的包含的内容涉及到值类型,就不可避免需要装箱、拆箱。请看下面的例子。
public class IntCollection : IList
 private ArrayList _Ints = new ArrayList();
 public int this[int index]
 { get { return (int)_Ints[index]; } }
 public int Add(int item)
 { _Ints.Add(item);
  return _Ints.Count - 1;}
 public void Remove(int item)
 { _Ints.Remove(item); }
  object IList.this[int index]
  { get { return _Ints[index]; }
  set { _Ints[index] = (int) }}
 int IList.Add(object item)
 { return Add((int)item); }
 void IList.Remove(object item)
 { Remove((int)item); }
 static void Main(string[] args)
 { IntCollection ints = new IntCollection();
  ints.Add(5); //装箱
  int i = ints[0]; //拆箱
少量装箱、拆箱对性能的影响不大,但是如果集合的数据量非常大,对性能还是有一定影响的。泛型能够避免对值类型的装箱、拆箱操作,您可以通过分析编译后的IL得到印证。
static void Main()
 List ints = new List();
 ints.Add(5); //不用装箱
 int i = ints[0]; //不用拆箱
泛型的实现
static void Swap(ref T a, ref T b)
{ Console.WriteLine("You sent the Swap() method a {0}",
 typeof(T));
&泛型类、结构
public class Point
 private T _x;
 private T _y;
 public T X
 { get { return _x; }
  set { _x = }}
 public T Y
 { get { return _y; }
  set { _y = }}
 public override string ToString()
 { return string.Format("[{0}, {1}]", _x, _y); }
泛型的Where
泛型的Where能够对类型参数作出限定。有以下几种方式。
&where T : struct 限制类型参数T必须继承自System.ValueType。
&where T : class 限制类型参数T必须是引用类型,也就是不能继承自System.ValueType。
&where T : new() 限制类型参数T必须有一个缺省的构造函数
&where T : NameOfClass 限制类型参数T必须继承自某个类或实现某个接口。
以上这些限定可以组合使用,比如: public class Point where T : class, IComparable, new()
泛型的机制
C#泛型代码在被编译为IL代码和无数据时,采用特殊的占位符来表示泛型类型,并用专有的IL指令支持泛型操作。而真正的泛型实例化工作以"on-demand"的方式,发生在JIT编译时。
&编译机制:
1. 第一轮编译时,编译器只为Stack(栈算法)类型产生&泛型版&的IL代码与元数据-----并不进行泛型类型的实例化,T在中间只充当占位符
2. JIT编译时,当JIT编译器第一次遇到Stack时,将用int替换&泛型版&IL代码与元数据中的T---进行泛型类型的实例化。CLR为所有类型参数为&引用类型&的泛型类型产生同一份代码;但如果类型参数为&值类型&,对每一个不同的&值类型&,CLR将为其产生一份独立的代码。
泛型的一些问题
&不支持操作符重载。我只知道这么多了
范型的意义
泛型的意义何在?类型安全和减少装箱、拆箱并不是泛型的意义,而是泛型带来的两个好处而已(或许在.net泛型中,这是最明显的好处了)。泛型的意义在于&&把类型作为参数,它实现了代码之间的很好的横向联系,我们知道继承为代码提供了一种从上往下的纵向联系,但泛型提供了方便的横向联系(从某种程度上说,它和AOP在思想上有相通之处)。在PersonCollection例子中,我们知道Add()方法和Remove()方法的参数类型相同,但我们明确无法告诉我们的程序这一点,泛型提供了一种机制,让程序知道这些。道理虽然简单,但这样的机制或许能给我们的程序带来一些深远的变化吧。
声明:该文章系网友上传分享,此内容仅代表网友个人经验或观点,不代表本网站立场和观点;若未进行原创声明,则表明该文章系转载自互联网;若该文章内容涉嫌侵权,请及时向
上一篇:下一篇:
相关经验教程
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.002 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益c#_百度百科
C#是发布的一种面向对象的、运行于之上的高级程序设计语言。并定于在微软职业开发者论坛(PDC)上登台亮相。C#是微软公司研究员Anders Hejlsberg的最新成果。C#看起来与Java有着惊人的相似;它包括了诸如单一继承、接口、与Java几乎同样的语法和编译成中间代码再运行的过程。但是C#与Java有着明显的不同,它借鉴了Delphi的一个特点,与COM(组件对象模型)是直接集成的,而且它是微软公司 .NET windows网络框架的主角。C#是一种安全的、稳定的、简单的、优雅的,由C和衍生出来的的编程语言。它在继承C和C++强大功能的同时去掉了一些它们的复杂特性(例如没有以及不允许多重继承)。C#综合了简单的可视化操作和C++的高运行效率,以其强大的操作能力、优雅的语法风格、创新的语言特性和便捷的面向编程的支持成为开发的首选语言。[1]
C#是的编程语言。它使得程序员可以快速地编写各种基于MICROSOFT .NET平台的应用程序,MICROSOFT .NET提供了一系列的和服务来最大程度地开发利用计算与通讯领域。C#使得C++程序员可以高效的开发程序,且因可调用由 C/C++ 编写的本机原生函数,因此绝不损失C/C++原有的强大的功能。因为这种关系,C#与C/C++具有极大的相似性,熟悉类似语言的开发者可以很快的转向C#。[2]
C#是公司在2000年6月发布的一种新的,主要由(Anders Hejlsberg)主持开发,它是第一个面向组件的编程语言,其源码会编译成msil再运行。它借鉴了的一个特点,与COM()是直接集成的,并且新增了许多功能及语法糖,而且它是公司.NET 网络的主角。[3]
C#读作C Sharp。最初它有个更酷的名字,叫做。微软从1998年12月开始了COOL项目,直到2000年2月,COOL被正式更名为C#。在1998年,语言的设计者Hejlsberg带领着公司的开发团队,开始了第一个版本C#语言的设计。在2000年9月,国际信息和通信系统标准化组织为C#语言定义了一个Microsoft公司建议的标准。最终C#语言在2001年得以正式发布。
原Broland公司的首席研发设计师安德斯·海尔斯伯格(An
ders Hejlsberg)在微软开发了Visual J++ 1.0,很快的由1.1版本升级到6.0版。公司认为Visual J++ 违反了Java开发平台的中立性,对微软提出了诉讼。日微软在举行的“职业开发人员技术大会”(PDC 2000)上,发表新的语言C#。C#语言取代了,语言本身深受 、C 和 C++ 的影响。[4]
C#是兼顾开发和应用开发的最佳实用语言,并且很有可能成为编程语言历史上的第一个“全能”型语言。看过这篇,不要把C#看成年轻后生了——只要是“”,就早晚当“球王”。C#1.0,纯粹的。[5]
1998年底,正在忙于新一代COM的设计工作,COM一直是组件化开发中非常成功的一种技术;但由于它仅提供了二进制层面上的统一,因此无法将类型信息和用于支持基础平台和开发工具的信息放到组件中,Java逐步走向成熟。微软学习Java的做法,将虚拟机的概念引入到了COM领域;同时,微软提出了“元数据”的概念,用于描述组件的类型信息和工具支持信息,并决定将其放入到组件当中。[6]
1998年12月,微软启动了一个全新的语言项目——COOL,这是一款专门为CLR设计的纯面向对象的语言,也正是本文的主角——C#的前身。[7]
1999年7月份,微软完成了COOL语言的一个内部版本。[7]
2000年2月份,微软才正式将COOL语言更名为C#。据说起这个名字是因为C#开发小组的人很讨厌搜索引擎,因此把大部分引擎无法识别的“#”字符作为该语言名字的一部分;还有一种说法是在音乐当中“#”是升调记号,表达了微软希望它在C的基础上更上一层楼的美好愿望——当然这些都只是传说,无从考证。又是历经了一系列的修改,微软终于在2000年7月发布了C#语言的第一个。[7]
C#旨在设计成为一种“简单、现代、通用”,以及面向对象的语言,此种语言的实现,应提供对于以下软件工程要素的支持:强类型检查、数组维度检查、未初始化的变量引用检测、自动垃圾收集(Garbage Collection,指一种自动技术)。软件必须做到强大、持久,并具有较强的编程生产力。此种语言为在分布式环境中的开发提供适用的组件开发应用。
为使程序员容易迁移到这种语言,的可移植性十分重要,尤其是对于那些已熟悉C和C++的程序员而言。对国际化的支持非常重要。C#适合为独立和嵌入式的系统编写程序,从使用复杂操作系统的大型系统到特定应用的小型系统均适用。[8-9]
:在C#中类的声明与和Java很相似。但是,不象C++,C#
C# Project
与是不支持继承。但是,与Java相同的是,一个结构体可以实现接口(interface)。Java的关键字已经被替换成,它起到了同样的作用。
类可以是抽象的和不可继承的:一个被申明成的类不能被实例化,它只能被用做一个基类,C#关键字lock就像Java关键字,它申明一个类不是抽象的,但是它也不能被用做另一个类的基类界面:就象在Java中一样,一个界面是一组方法集合的抽象定义。当一个类或结构体实现一个界面的时候,它必须实现这个界面中定义的所有方法。一个单一的类可以实现几个界面,也许以后会出现一些微妙的差别,但是这个特点看起来与Java相比没有变化。[10]
在中,一个接口是一组方法集合的抽象定义.当一个类或结构体实现一个接口的时候,它必须实现这个接口中定义的所有方法.一个单一的类可以实现几个接口.也许以后会出现一些微妙的差别,但是这个特点看起来与Java相比没有变化。:条件表达式的结果是布尔数据类型,布尔数据类型是这种语言中独立的一种数据类型.从布尔类型到其他类型没有直接的转换过程.布尔常量和false是C#中的关键字.错误处理:如Java中那样,通过抛出和捕捉异常对象来管理错误处理过程.内存管理:由底层.NET框架进行自动内存垃圾回收。
:条件表达式的结果是数据类型,布尔数据类型是这种语言中独立的一种数据类型,从布尔类型到其他类型没有直接的转换过程,布尔常量true和false是C#中的关键字。错误处理:如Java中那样,通过抛出和捕捉异常对象来管理错误过程。[11]
:由.NET框架进行自动内存垃圾回收。一个基本的C#类中包含成员、、和方法。属性可以是静态或实例成员。
:是其他类型为确保它们支持某些操作而实现的引用类型。接口从不直接创建而且没有实际的表示形式,其他类型必须转换为接口类型。
一个接口定义一个协定。实现接口的类或结构必须遵守其协定。可以包含方法、、和事件作为成员。
:C#是一个强类型的语言,它的数值类型有一些可以进行隐式转换,其他的必须显式转换,隐式转换的类型只能是长度短的类型转换成长的类型,int可以转换成、、、,反之必须显式的转换。
:程序直接编译成标准的二进制可执行形式.但C#的源程序并不是被编译成二进制可执行形式,而是一种中间语言(IL),类似于JAVA字节码。如果前面的Hello World程序被保存成一个
c#与asp.net权威指南教程
文本文件并被命名为Hello.cs,它将被编译成命名Hello.exe的。
C#程序不能直接编译成标准的可执行形式,与 Java 类似,它被编译成为中间代码(Microsoft Intermediate Language),然后通过 .NET Framework 的虚拟机——被称之为通用语言执行层(Common Language Runtime, CLR)——执行。
一个C#的结构体与C++的结构体是相似的,因为它能够包含数据声明和方法.但是,不象C++,C#结构体与类是不同的而且不支持继承.但是,与Java相同的是,一个结构体可以实现接口。
:C# 中存在指令支持条件,警告,错误报告和编译行控制.可用的预编译指令有:#define,#undef,#if,#elif,#else,#endif,#warning,#error,#line。
没有了#include伪指令,无法再用#define 语句对符号赋值,所以就不存在源代码替换的概念--这些符号只能用在#if和#elif伪指令里.在#line伪指令里的数字(和可选的名字)能够修改行号还有#warning和#error输出结果的文件名。
:一些操作符能够被,而另一些则不能.特别的是,没有一个赋值运算符能够被重载.能够被重载的单目操作符是:+ - ! ~ ++ -- true false 能够被重载的二元运算符是:+、 - 、*、 /、 %、 &、 |、 ^、 && 、&&、 ==、 !=、 &、 & 、&= 、&=。[13]
:C# 中的类型一共分为两类,一类是(Value Type),一类是(Reference Type)。值类型和引用类型是以它们在计算机内存中是如何被分配的来划分的。值类型包括 结构和枚举,引用类型包括类、接口、委托 等。还有一种特殊的值类型,称为简单类型(Simple Type),比如 byte,int等,这些简单类型实际上是FCL类库类型的别名,比如声明一个int类型,实际上是声明一个System. Int32结构类型。因此,在 Int32类型中定义的操作,都可以应用在int类型上,比如 “123.Equals(2)”。
所有的值类型都隐式地继承自System.ValueType类型(注意System.ValueType本身是一个类类型),System.ValueType和所有的引用类型都 继承自 System.Object基类。不能显式地让结构继承一个类,因为C#不支持多重继承,而结构已经隐式继承自ValueType。
:(stack)是一种后进先出的数据结构,在内存中,变量会被分配在堆栈上来进行操作。堆(heap)是用于为类型实例(对象)分配空间的内存区域,在堆上创建一个对象,会将对象的地址传给堆栈上的变量(反过来叫变量指向此对象,或者变量引用此对象)。[14]
:微软在用户选择何时应该编译成机器码的时候
C#开发QTP脚本标志
是留了很大的余地.微软公司很小心的声称MSIL不是解释性的,而是被编译成了机器码.它也明白许多--如果不是大多数的话--程序员认为Java程序要不可避免的比C编写的任何东西都要慢.而这种实现方式决定了基于MSIL的程序(指的是用C#,,&Managed C++&--C++的一个符合CLS的版本--等语言编写的程序)将在性能上超过&解释性的&Java代码.当然,这一点还需要得到事实证明,因为C#和其他生成MSIL的编译器还没有发布.但是Java JIT编译器的普遍存在使得Java和C#在性能上相对相同.象&C#是编译语言而Java是解释性的,&之类的声明只是商业技巧.Java的中间代码和都是中间的汇编形式的语言,它们在运行时或其它的时候被编译成机器代码。[16]
基本数据类型:C#拥有比C/C++或者Java更广泛的数据类型.这些类型是bool、byte、ubyte、short、ushort、int、uint、long、ulong、float、double和decimal,像Java一样,所有这些类型都有一个固定的大小.又像C和C++一样,每个数据类型都有有符号和无符号两种类型.与Java相同的是,一个字符变量包含的是一个16位的Unicode字符,C#新的是decimal数据类型,对于货币数据,它能存放28位10进制数字。[16]
两个基本类:一个名叫的类是所有其他类的基类。而一个名叫string的类也象object一样是这个语言的一部分.作为语言的一部分存在意味着编译器有可能使用它,无论何时在程序中写入一句带引号的字符串,编译器会创建一个string对象来保存它。[16]
参数传递:方法可以被声明接受可变数目的参数.缺省的参数传递方法是对基本数据类型进行值传递。ref关键字可以用来强迫一个变量通过,这使得一个变量可以接受一个。out关键字也能引用传递过程,与ref不同的地方是,它指明这个参数并不需要初始值。[16]
COM的集成:C#对Windows程序最大的卖点可能就是它与COM的无缝集成了,COM就是微软的Win32组件技术.实际上,最终有可能在任何.NET语言里编写COM客户和。C#编写的类可以子类化一个已存在的;生成的类也能被作为一个COM组件使用,然后又能使用,比方说,语言子类化它从而得到第三个COM组件。这种现象的结果是导致了一个运行环境的产生,在这个环境里的组件是网络服务,可用任何.NET语言子类化。[16]
索引下标:一个与除了不使用属性名来引用类成员而是用一个方括号中的数字来匿名引用(就象用数组下标一样)以外是相似的。[16]
代理和反馈:一个代理对象包括了访问一个特定对象的特定方法所需的信息.只要把它当成一个聪明的方法指针就行了。代理对象可以被移动到另一个地方,然后可以通过访问它来对已存在的方法进行类型安全的调用.一个反馈方法是代理的特例.event关键字用在将在事件发生的时候被当成代理调用的方法声明中。[16]
C#所开发的程序源代码并不是编译成能够直接在上执行的本地代码。与Java类似,它被编译成为中间代码,然后通过.NET的虚拟机——被称之为通用语言运行时()——执行。 所有的.Net编程语言都被编译成这种被称为(Microsoft Intermediate Language )的中间代码。因此虽然最终的程序在表面上仍然与传统意义上的可执行文件都具有“.”的后缀名。但是实际上,如果计算机上没有安装.Net Framework,那么这些程序将不能够被执行。 在程序执行时,.Net Framework将中间翻译成为二进制机器码,从而使它得到正确的运行。最终的二进制代码被存储在一个缓冲区中。所以一旦程序使用了相同的代码,那么将会调用缓冲区中的版本。这样如果一个.Net程序第二次被运行,那么这种翻译不需要进行第二次,速度明显加快。[17]
stackalloc
sealed[18]
部分描述:
abstract:可以和类、方法、属性、索引器及事件一起使用,标识一个可以扩展但不能被实体化的、必须被实现的类或方法。
as:一个转换操作符,如果转换失败,就返回null。
base:用于访问被派生类或构造中的同名成员隐藏的基类成员。
catch:定义一个代码块,在特定类型异常抛出时,执行块内代码。
checked:既是操作符又是语句,确保编译器运行时,检查整数类型操作或转换时出现的溢出。
const:标识一个可在编译时计算出来的变量值,即一经指派不可修改的值。
delegate:指定一个声明为一种委托类型。委托把方法封装为可调用实体,能在委托实体中调用。
enum:表示一个已命名常量群集的值类型。
event:允许一个类或对象提供通知的成员,他必须是委托类型。
explicit:一个定义用户自定义转换操作符的操作符,通常用来将内建类型转换为用户定义类型或反向操作,必须再转换时调用显示转换操作符。
extern:标识一个将在外部(通常不是c#语言)实现的方法。
finally:定义一个代码块,在程序控制离开try代码快后执行。参见try和catch。
fixed:在一个代码块执行时,在固定内存位置为一个变量指派一个指针。
foreach:用于遍历一个群集的元素。
goto:一个跳转语句,将程序执行重定向到一个标签语句。
implicit:一个操作符,定义一个用户定义的转换操作符,通常用来将预定义类型转换为用户定义类型或反向操作,隐式转换操作符必须在转换时使用。
interface:将一个声明指定为接口类型,即实现类或构造必须遵循的合同。
internal:一个访问修饰符。
namespace:定义一个逻辑组的类型和命名空间。
operator:用来声明或多载一个操作符。
out:标识一个参数值会受影响的参数,但在传入方法时,该参数无需先初始化。
params:声明一个参数数组。如果使用,必须修改指定的最后一个参数,允许可选参数。
readonly:标识一个变量的值在初始化后不可修改。
ref:标识一个参数值可能会受影响的参数。
sealed:防止类型被派生,防止方法和property被覆载。
sizeof:一个操作符,以byte为单位返回一个值类型的长度。
stackalloc:返回在堆上分配的一个内存块的指针。
struct:是一种值类型,可以声明常量、字段、方法、property、索引器、操作符、构造器和内嵌类型。
throw:抛出一个异常。
try:异常处理代码块的组成部分之一。try代码块包括可能会,抛出异常的代码。参阅catch和finally关键字。
typeof:一个操作符,返回传入参数的类型。
unchecked:禁止溢出检查。
unsafe:标注包含指针操作的代码块、方法或类。
using:当用于空间时,using关键字允许访问该命名空间中的类型,而无需指定其全名。也用于定义finalization操作的范围。
virtual:一个方法修饰符,标识可被覆载的方法。
volatile:标识一个可被操作系统、某些硬件设备或并发线程修改的attribute。[18-19]
C# 1.0-纯粹的面向对象
在2003年5月,微软推出了Visual Studio .NET 2003,同时也发布了C#的改进版本——C# 1.1。
这一时期的C#(以下称为C# 1.x)提出了纯粹的面向对象概念。C++并非纯的,为了和C兼容以及提供更高的执行效率,它保留了很多模块化的东西。C#还通过类类型、值类型和接口类型的概念形成了统一的类型系统。
尽管C# 1.x提供了如此多的新鲜概念,但实际上,这些概念都是由提出的。因此当将一个C#源程序编译为可执行文件时,编译器做的工作相对而言并不多。需要编译器代劳的是要将一个简单的委托定义语句翻译为一个继承System.MulticastDelegate类型定义。
C# 2.0-泛型编程新概念
微软在2004年的6月份发布了Visual Studio2005的第一个Beta 版,同时向开发者展示了C#语言的2.0版本。2005年4月,微软发布了Visual Studio 2005 Beta2,这已经是具备了几乎全部功能的VisualStudio,包括的产品有SQL Server2005、Team Foundation Server和TeamSuite。这时的C#编译器已经能够处理C# 2.0中所有的新特性。[20]
C# 2.0为开发者带来的最主要的特性就是编程能力。和面向对
Microsoft Visual C# .NET Step by Step
象思想一样,泛型思想也是一种已经成熟的编程思想,但依然是没有哪一种主流开发语言能够支持完备的泛型概念。这主要是因为泛型的概念在一定程度上对面向对象概念进行冲击,同时,由于在编译期间对类型参数的完全检测很难做到,很多问题会被遗留到运行时。C# 2.0别出心裁,对泛型类型参数提出了“约束”的新概念,并以优雅的语法体现在语言之中。有了约束,结合编译器强大的类型推断能力,可以在编译时发现几乎所有“危险”的泛型应用。[22]
C# 2.0的另一个突出的特性就是,用来取代一些短小的并且仅出现一次的委托,使得语言结构更加紧凑。匿名方法除了可以使得事件处理器的编写更加精简以外,还将开发者带入了程序设计的一个新的领域——函数式编程,曾经有高人就用匿名方法结合泛型编程实现了函数式编程中的重要结构—— Lambda 表达式。尽管这种实现显得很繁琐而且不易理解,但毕竟是实现了。
C#3.0-(研发代号“Orcas”)
2005年9 月份的大会——C#3.0(研发代号“Orcas”——魔鬼)的技术预览版。说到C# 3.0,就不得不提一下微软的LINQ 项目,LINQ(语言集成查询,Language Integrat
ed Query)提出了一种通过面向对象语法来实现对非面向对象数据源的查询技术,可查询的数据源从关系型数据库延伸到一般意义上的集合(如数组和列表)以及XML。而C# 3.0则是率先实现了LINQ的语言。
在C# 3.0中,可以用类似于SQL语句的语法从一个数据源中轻松地得到满足一定条件的对象集合。例如要查找一个字符串数组names中所有长度大于5的字符串,就可以写:var longname = from n in names wheren.Length & 5
这样就得到一个新的字符数组longname,其中包含了所需要的结果。这种语句称作查询语句,与SQL语句唯一的区别是C#中的查询语句往往把select子句放到最后(这反而倒有些类似于中文的阅读顺序了)。初次看到这样一个语句,可能会有很大疑问:这还是C#语言吗?这的确是合乎语法规则的C#代码,而且编译器可以识别这种语法。然而实际上,C#编译器并不会对这种语法进行实际的的编译,而是将其翻译为正常的方法调用。[23]
C# 4.0动态编程
C# 4.0 新增 dynamic关键字,提供(dynamic programming),把既有的静态物件标记为动态物件,类似javascript, Python 或 Ruby[24-25]
根据资料评价显示:C#几乎集中了所有关于和研究的最新成果:面向对象、类型安全、组件技术、自动内存管理、跨平台、版本控制、代码安全管理……。尽管像很多人注意到的一样,罗列上述特性时,总是让人想到JAVA,然而C# 确实走得更远。但现实的情况是,非技术的因素往往更能决定一个产品的未来,尤其在计算机软件的历史上,技术卓越的产品,如OS/2、Mac OS、UNIX等,都败在了Windows漂亮的界面上。JAVA的用户主要是网络服务的开发者和嵌入式设备软件的开发者,嵌入式设备软件不是C# 的用武之地,而在网络服务方面,C# 的即时编译和本地代码Cache方案比JAVA虚拟机具有绝对的性能优势。何况C# 一旦成为一个像C++ 一样的公共的标准,软件开发商既可以省去JAVA的许可证费用,也不必担心成为微软的奴隶,那些反微软的人士和主张厂商独立的人士可能也不会有什么意见。这可能正是微软所期待的。[26]
如果把C# 和
在网络服务领域的争夺比作未来制空权的争夺,那么C# 和传统通用快速开发工具——VB、DELPHI等的较量将是地地道道的白刃战。可能最惨的程序员就是VB程序员,在微软,VB就像离任的克林顿,不但失去了所有的光辉,而且乱事缠身。[26]
其实在中真正的霸主多年来一直是C++,所有的操作系统和绝大多数的商品软件都是用C++作为主要开发语言的。JAVA的程序员绝大多数也是C++的,PHP的成功里面也有类似C++的语法的功劳。在操作系统、设备驱动程序、视频游戏等领域,C++在很长的时间内仍将占据主要地位,而在数量最大的应用软件的开发上,C# 很可能取代C++的位置。首先,C# 和JAVA一样,简直就是照搬了C++的部分语法,因此,对于数量众多的C++程序员学习起来很容易上手,另外,对于新手来说,比C++要简单一些。其次,Windows是占垄断地位的平台,而开发Windows应用,当然微软的声音是不能忽略的。最重要的是,相对于C++,用C# 开发应用软件可以大大缩短开发周期,同时可以利用原来除用户界面代码之外的C++代码。[26]
但是,C# 也有弱点。首先,在一些版本较旧的Windows平台上,C# 的程序还不能运行,因为C# 程序需要 .NET运行库作为基础,而 .NET运行库作为(及以后版本)的一部分发行,
和 Windows 2000用户只能以的形式安装使用。其次,C# 能够使用的组件或库还只有 .NET 运行库等很少的选择,没有丰富的第三方软件库可用,这需要有一个过程,同时各软件开发商的支持也很重要。第三,JAVA的成功因素里有一些是反微软阵营的吹捧,虽然“只写一次,到处运行”只是一句口号,但毕竟已经是一种成熟的技术。而C# 的鼓吹者只有名声不佳的微软,且只能运行在Windows上。实际上这两种语言都不是不可替代的,理智的说,对软件开发商而言,什么用的最熟什么就是最好的工具。尤其对C++的使用者,C# 没有带来任何新东西,因为.NET运行库在C++中也可以使用,没有要换的绝对的理由。[26]
C# 将不可避免地,在Windows平台上成为主角,而JAVA将在、Linux等平台上成为霸主,C++ 将继续在系统软件领域大展拳脚。非常有意思的是,这些语言的语法极其接近,因为JAVA和C# 都是由C++发展而来的。其他的开发工具当然还会在相当长的时间里继续他们的旅程,不过在市场份额上,将不可避免地受到冲击。[26]
.csdn网&#91;引用日期&#93;
.领测网&#91;引用日期&#93;
.现代快报网&#91;引用日期&#93;
.中国知网&#91;引用日期&#93;
.知网&#91;引用日期&#93;
.知网&#91;引用日期&#93;
.csdn博客网&#91;引用日期&#93;
.中文业界网&#91;引用日期&#93;
.教育网[&#91;引用日期&#93;
.csdn博客(原创)&#91;引用日期&#93;
.51cto网&#91;引用日期&#93;
.有材网&#91;引用日期&#93;
.cn博客(原创)&#91;引用日期&#93;
.博海时空.&#91;引用日期&#93;
.iquicktest网&#91;引用日期&#93;
.北京华腾网络网&#91;引用日期&#93;
.新浪博客(原创)&#91;引用日期&#93;
.cnblog网&#91;引用日期&#93;
.csdn博客网(原创)&#91;引用日期&#93;
.搜狐网&#91;引用日期&#93;
.ebookee网&#91;引用日期&#93;
.csdn博客(原创)&#91;引用日期&#93;
.51cto网&#91;引用日期&#93;
.黑客联盟网&#91;引用日期&#93;
.酷勤网&#91;引用日期&#93;
.育龙网&#91;引用日期&#93;
中国电子学会(Chinese Instit...
提供资源类型:内容

我要回帖

更多关于 泛型是什么意思 的文章

 

随机推荐