【笔记】Java

  • Java有8种基本类型:int、short、long、byte(-128~127)、float、double、char、boolean,JAVA没有无符号类型
  • Java的基本类型都有对应的包装类,包括Integer、Long、Float、Double、Short、Byte、Character、Boolean,前6个派生于公共的超类Number,包装类是不可变和无法派生的
  • Java字符串类型为java.lang.String
  • C#有14种基本类型:sbyte、byte、short、ushort、int、uint、long、ulong、IntPtr、UIntPtr、float、double、char、bool
  • C#字符串类型为Sytem.String,别名为string,为引用类型
  • Java不支持运算符重载(但内部重载了String的加运算符),C#支持运算符重载
  • C#支持foreach-in循环,而Java支持for-<:>循环
  • Java字符串比较需要用equals方法(因为没有重载相等运算符),C#字符串比较可以使用==
  • Java中Objects.requireNonNull或者Objects.requireNonNullElse用于判断或拒绝Null值
  • Java中Getter方法返回可变对象引用时破坏了封装性,对象可以被外部进行改变
  • Java用final定义常量,final保证了该字段只能被初始化一次,通常是在构造函数中初始化。当字段是引用类型时,final只保证引用本身不会改变,而引用指向的内容可以改变
  • C#使用const定义编译时常量,使用readonly定义运行时常量,编译时常量在编译时期就替换为具体的值,该值只能是字面量,const常量是静态的。而readonly常量可以在实例创建时动态计算,类似于Java的final常量
  • 字段没有显式设置初值时会自动赋默认值,局部变量必须初始化
  • Java初始化块在构造器之前运行,多个块按声明顺序执行
    class Test{
    
        int a;
    
        {
            a = 2;
        }
        //最终 a = 1
        public Test(){
            a = 1;
        }
    
        public int getA() {
            return a;
        }
    }

    可以在块前加static表示静态初始化块,Java没有静态构造函数

  • Java使用包来组织类,而C#使用命名空间来组织类。Java包使用域名的逆序来确保唯一性,Java的包结构与项目文件夹的结构是对应的,C#命名空间则与项目文件夹结构没有关系。在编译器看来,嵌套的包或命名空间没有任何关系
  • Java使用package来定义当前包名,import来导入包,C#使用namespace来定义当前命名空间,using来导入命名空间
  • Java使用extends来表示继承,使用implements来实现接口,C#使用<:>来表示继承和实现
  • Java使用this表示当前对象,super表示超类,this和super可以用于构造方法中调用该类或者超类的构造方法,该调用必须是构造方法第一条语句。如果子类的构造器没有显式调用超类的构造器,将自动调用超类的无参构造器,如果没有无参构造器,编译会发生错误。
  • C#使用this表示当前对象,base表示超类,通过方法名后的<:>语法可以用于构造方法中调用该类或者超类的构造方法。
  • Java的方法默认可以重写,如果在子类中定义了一个与超类相同的方法,那么子类中的这个方法就会重写超类中这个相同签名的方法。允许子类重写方法的返回类型改为原返回类型的子类型,重写方法时,子类方法不能低于超类方法的可见性
  • C#的方法默认无法重写,必须使用virtual来标记可以重写的方法,重写时必须使用override来标记
  • Java使用final修饰类来表示该类不可扩展,无法被继承,使用final修饰方法表示该方法无法被覆盖
  • C#使用sealed修饰类来表示该类不可扩展,无法被继承,使用sealed和override同时修饰方法或属性可以在重写时保证自身的子类无法再重写该方法或属性
  • Java使用instanceof来判断某个对象是否属于某个类、某个类的子类、某个接口
  • C#使用is来判断某个对象是否属于某个类、某个类的子类、某个接口、某个匹配的可空类型Nullable、某个匹配的装箱/拆箱类型
  • Java使用abstract修饰类来表示该类是抽象的,不可实例化。使用abstract修饰方法表示该方法是抽象方法,不需要实现。包含一个或多个抽象方法的类本身必须被声明为抽象的。抽象类无法实例化,但抽象类的对象变量可以引用非抽象子类的对象
  • Java中所有类的超类都是Object,只有基本类型不是对象。除了接口,C#中几乎所有类型的超类都是Sytem.Object,包括所有值类型(基本类型需要经过装箱)、所有类类,但某些指针类型不继承于Object。C#中所有非指针类型都可以转换为Object
  • Java使用<…>来表示可变参数,C#使用params来表示可变参数
  • Java中接口可以包含:静态常量、没有实现的抽象方法、具有默认实现的实例方法、具有实现的静态方法、嵌套类型(nested type)。Java中接口的所有方法都默认是public的,接口不能有实例字段,但可以有常量,接口字段默认是public static final的。
  • Java8中允许接口中增加静态方法,为[为该接口类型提供的静态方法]提供了放置的位置。Java9中允许接口中定义private的静态方法和实例方法,private的静态方法用于接口中静态方法的代码重用,private的实例方法用于接口中default方法的代码重用。只有一个抽象方法的接口称为函数式接口,函数式接口可以用lambda表达式提供。
  • Java中接口可以为方法提供默认实现,使用default关键字修饰。当继承一个具有默认实现的方法的接口时,可以重定义该方法,不使用default关键字可以将其重定义为抽象方法,使用default关键字和新的方法体可以重定义方法的实现。
  • C#中接口可以包含:没有实现的实例方法、具有默认实现的实例方法、实例属性、实例事件、实例索引器、具有实现的静态构造器、静态方法、静态字段、静态常量、静态运算符重载。C#11开始,接口可以包含static abstract的方法和属性。C#接口的默认实现不需要default关键字
  • Java中嵌套类分为两种:实例嵌套类(用class定义,也叫inner class,即内部类)、静态嵌套类(用static class定义),Java中要创建内部类对象必须先创建其外部类对象,内部类可以直接访问外部类的所有成员,其原理是Java编译器会在内部类保留一个对外部类对象的引用,并在内部类对象构造时传入对应的外部类对象。在虚拟机看来,内部类和其他类没有任何区别,内部类对象对外部类对象的私有属性的访问是通过编译器在外部类增加对应的方法来实现的。静态嵌套类则不创建对外部类对象的引用。
  • C#中嵌套类和Java类似,但C#的实例嵌套类,即内部类,不会自动创建对外部类对象的引用,需要手动实现。