C#和java之间的一些差异与共性

C#与java之间的一些共性和差异整理

隐藏:
与java中的重写几乎一致,但是需要添加new关键字让编译器知道,否则会有警告


虚方法:
1.声明为virtual的方法就是虚方法,在子类中使用override进行重写,当程序发现该方法是虚方法时,会去寻找子类中是否重写了该方法,如果被重写了,那么就调用子类中的方法,所以重写是多态实现的一种重要的方式,也称为动态绑定,而重载则是在程序编译阶段就进行的,所以叫静态绑定,也是编译前绑定
2.重写虚方法必须具有相同的可访问性,基类中的虚方法不能是private的
3.不能重写static方法或者非虚方法,覆盖使用的是new关键字。而非override
4.方法、属性、索引器、事件都可以用虚方法或者重写
5.与java中的抽象方法类似,但是虚方法可以拥有方法体,同时不一定要被重写,抽象方法则必须被重写


字段和属性:
1.通过设置属性的方式,来创造类似javabean中的set和get方法、
属性是public的。字段是private的,属性的名称要自己设置,但是最好和字段名字要相近,首字母大写,同时属性的数据类型和字段的数据类型要一致,可以使用CTRL+R+E的方式进行快捷封装。


2.将set属性删除,就可以让属性成为只读属性,对字段进行保护,get可以获取字段的值。set和get类似于java中的方法,可以在set方法中对属性的值进行检查,过滤,防止一些不合理的数据出现。


值类型和引用引用类型(值传递和引用传递):
1.基本数据类型,int bool char double等为值类型,是存储在栈中的(内存),当作用域结束时销毁,所以存储速度快
,对于值类型,有关赋值等相关的操作是copy了一份值的副本,因而其中一方更改不会影响到另外以防,例如A=1 B=A 修改A的值和B的值互不影响,各自进行管理,


2.引用类型: 类(String类型属于类),数组,接口等对象,就是引用类型,它们是存储在堆中的(物理硬盘),所以速度会较慢,但是他们的赋值操作,是会互相影响的。 例如: Dog dog=new Dog();    Dog dog2=dog; 这里的操作是创建了一个dog对象,同时将这个对象赋值给了dog2引用。
这里的dog 和dog2 是对象的引用,是存储在栈中的, 而new Dog()这个真正的对象中包含的数据是存储在堆中的。
所以dog和dog2指向的是同一个对象,因而如果dog或dog2对这个new出来的dog对象进行了修改,那么dog和dog2在调用其中的属性的时候,都是调用的修改后的属性。 


例子:可以理解成,两个小朋友一人有一个棒棒糖(值类型),各自吃各自的,自己的吃
完了。对方的不一定吃完。   然后两人各有一个遥控器,都能对电视机进行控制,当一个人切到了天线宝宝的节目的时候,另外一个人看到的也是天线宝宝,即引用传递修改的是同一个东西,而值传递修改的是两个东西,是各自的副本


结构和类:
1.结构中的字段不能有初始值,类中的字段可以有初始值,结构中的字段可以和类一样有属性,结构和类都能有构造方法,但是结构中不能有显式的无参构造方法,可以有带参的构造方法,同时要为结构中的所有字段赋值,如果有一个没有赋值,都会报错。
  类中则无参带参都可以有,同时没有必须为所有字段赋值的限定。


2.结构可以不必实例化,直接就能访问它的属性和方法。 类则不能。 


3. 结构不支持继承,类支持继承,编译器会自动定义结构的无参构造方法


枚举类型:属于值类型,在枚举中不能定义字段属性和方法,枚举是从0递增的增数值,
限定了某些类型的取值范围,例如性别。可以防止错误的输入
赋值:枚举名.枚举中的属性名  例如 Gender.男 或者使用强制类型转换(Gender)0


引用传参和值传参(引用传递和值传递):
1.按引用传参,方法修改形参,通常实参也会被修改,
2.按值传参,方法修改形参,实参不会被修改


ref关键字:
添加ref关键字,可以让至传递的值类型变量,转化为按引用传参,但要注意在传递的双方都要带上ref修饰(声明和调用时),同时属性不允许作为ref关键字修饰的参数,所以需要单独声明一个变量来存储属性的值。


out关键字:
用来获取结果。可以视作return的补充。


调用顺序:
1.先实例化父类中的成员----然后调用父类中的构造函数---然后调用子类中的实例成员----然后调用子类的构造函数
2.使用base()可以进行显式的调用父类的构造函数,使用this()则调用当前子类自己的构造函数,括号中可以带参也可以是无参的


抽象类和抽象方法:
与java基本类似,抽象成员必须是方法属性时间索引器,


密闭类和密闭方法:
sealed修饰,作用类似于java中的final,如果要修饰变量,则使用const


接口:
与java的语法规则基本一致,但是在继承了一个类同时实现多个接口的时候,必须将继承的类摆在:的最前面一个


静态成员,静态类:
1.静态成员不能访问实例成员因为实例成员需要new出对象以后才会被创建,所以实例成员可以访问静态成员,静态成员无法访问实例成员


2.静态类不能创建实例,也不能被继承,可以定义一个静态的构造函数,主要应用于基础类库,和扩展方法


如何扩展方法:
如果有源代码,直接添加新的方法。
如果不能修改,但也不是密闭类,可以通过子类来进行扩展
如果以上操作都无法实现,则可以使用静态类进行扩展
1.扩展方法所属的类必须是一个静态类,2.同时该方法本身也必须是一个静态方法
3.扩展方法的第一个参数类型必须是this+类名
例子:   static class Guid{
             static public void HowTo(this Dog dog){


                }
       
          } 
最后直接通过 Dog dog =new Dog();
           dog.howTo();
就可以对扩展的方法进行访问了,类似于这个方法就是原生在Dog类(需要被扩展额外方法的类)中的。


自定义转换:
1.隐式转换必须是静态的公共方法并且使用 implicit operator关键字
: public static implicit operator Cat(Dog dog) 
{  
         return new Cat();
  }
括号外的对象是传入的参数是想要被隐式转换后的对象类型


2.显式转换与隐式转换的定义基本一致,差别在于使用explicit关键字
: public static explicit operator Dog(Cat cat)

         return new Dog();
 }
 括号外的对象是传入的对象想要被显式转换后的对象类型


3.重载运算符:利用现有的运算符,针对自定义的类或者结构定义某种运算操作,(不能是自己创造的运算符,不能是预定义的类型如int String等)。重载运算符可以简化自定义类型的操作,更加方便和直观。
  当运算符是一元运算符的时候 操作数必须是类或者结构中的一种,如果运算符是二元的时候,两个操作数中必须有一个是类或结构


public static Pet operator ++(Pet pet){
++Pet.age;
}
 pet++; 此时pet对象因为重载了++运算符,所以,进行pet++的时候,是让pet的age进行了+1
 pet.showAge();


泛型,约束:
通过约束,更好的利用泛型,泛型参数可以有多个即T1 T2 T3 
同时约束就是利用where语句对特定的泛型进行约束,
void  home<T> where T: (1.主约束 2.接口约束 3.构造约束)
主约束只能有一个可以是某个具体的类名,class,结构, 接口约束可以有任意个
当具体到某个类名的时候,传入的只能是这个类的类型的对象,class则表示必须传入一个类类型对象,即不能是int之类的值类型。当确定了传入的类之后,就可以直接调用传入的这个主约束中的方法,接口也是同理,当传入构造约束以后。就可以在泛型方法中创建实例对象了。


集合:
Arraylist是动态数组,什么都能放,是一维的,但是也是类型不安全的,所以有了List<T>泛型,但是这里就会存在装箱和拆箱的操作,性能上有损失两者都有add remove,count等方法,可以通过索引来访问和删除指定索引位置的数据


Dictionary字典,类似于java中的Map。它的数量也是count方法,添加的时候需要添加两个,一个是key一个是value。访问则直接通过key来进行访问,更加的方便管理,但是


stack栈是先进后出,类似只有一个开口的容器,
pop出栈,push入栈,peek获取栈顶元素


queue队是先进先出,类似于水管,两头都开口的容器。
dequeue 出队, enqueue入队


委托:
委托就是持有一个或者多个方法的对象!并且该对象可以执行可以传递,使用delegate声明
可以将对象的方法赋给委托对象
delegate void A();
 A del=dog.speak;
 del+=dog.run;


使用方式:与使用函数一样直接使用委托名加括号的方式del(); 
  委托可以持有多个方法,调用一次,
就可以把委托中的方法全部执行一遍


Lambda表达式:即匿名的委托
del=()=>{}
del+=()=>{
方法具体.....
}


事件:可以理解为是一种封装的,受限制的委托
1订阅:关注某个事件发生
2发布:通知某个事件发生
3注册:想要在事件发生时被通知,必须要注册
触发,即当事件发生时,调用订阅者的注册函数,注册就是告诉发布者应当调用哪个注册函数


事件的订阅 newdog += 方法  表示关注  newdog -= 方法 表示取消关注,方法可以是实力方法,静态方法,匿名方法,Lambda表达式
其中的newdog就是事件名,即想要关注的是哪个事件


事件触发 if(newdog!=null){
          newdog();
  }
对事件进行判断,如果不为空,则代表有关注者,也就是被订阅了,那么就执行这个委托事件


public delegate void handler(); //定义一个委托类型
public static event handler newdog;       //定义一个委托事件


在需要进行事件触发的地方进行事件的判断,与触发


同时进行事件的订阅,也就是注册 dog.newdog += 方法
---------------------
作者:YXJHASADREAM
来源:CSDN
原文:https://blog.csdn.net/qq_36854407/article/details/79188865
版权声明:本文为博主原创文章,转载请附上博文链接!

原文地址:https://www.cnblogs.com/GarfieldEr007/p/10016881.html