Java语言概要

时间:2024-11-15 22:03:37
  • Java把源代码(SourceCode)翻译成字节码(ByteCode):javac MyClass.java,再在Java虚拟机(JVM)上执行字节码:java MyClass。
  • Java是基于面向对象编程(OOP)的,OOP的三原则是封装(Encapsulation)、继承(Inheritance)和多态(polymorphism),封装是为了捆绑数据和代码,继承是为了层次化分类,多态是为了“一个接口,多种方法”
  • Java的标识符由字母、数字、下划线_、美元符$组成,数字不能开头。Java的注释和C的注释相同,还多了一种文档注释。
  • Java是强类型语言,分为基本类型类类型基本类型有8种,整型有4个:byte(8位)、short(16位)、int(32位)和long(64位),浮点型有2个:float(32位)和double(64位),字符型和布尔型各有1个:char(16位)和boolean(8位),基本类型是基于面向过程的,无需使用new语句创建,而对象必须使用new语句创建,我们可以把基本类型封装在对象中,这样的对象叫做类型封装器,分别是ByteShortIntegerLongFloatDoubleCharacterBoolean,其中前6个都继承了Number类,基本类型与类型封装器之间可以根据需要自动装箱自动拆箱,整型不支持无符号,所有整型都是有符号的,字符型不是基于ASCII而是基于Unicode的,字符型本质就是整型,可以进行整数操作,布尔型只有true和false,布尔型与整型不能相互进行转换,类型转换分为自动类型转换强制类型转换,数字型、字符型和布尔型之间不能相互转换,两种类型兼容(同是数字型)可以进行类型转换,自动类型转换也叫扩宽转换,强制类型转换也叫缩小转换,浮点型转换为整数型时会截去小数部分,表达式中会自动类型提升:byte, short, char -> int -> long -> float -> double。
  • 可以使用字面值和变量指代数据,字面值(Literal)有整型字面值、浮点型字面值、字符型字面值、布尔型字面值和字符串字面值,前面四个都是基本类型,只有最后一个是类类型,变量在类中叫实例变量,块可以嵌套,内部块的变量可以访问外部块的变量,外部块的变量不能访问内部块的变量,内部块的变量不能与外部块的变量同名,但实例变量可以与方法中的变量同名,此时实例变量会被覆盖,可以使用self关键字显式访问。
  • 运算符(Operator)分为算术运算符位运算符布尔运算符和其他运算符,算术运算符可以作用在数字型和字符型中,此外还有赋值运算符instanceof等,使用instanceof运算符可以在运行时判断对象的类型,表达式(Expression)会根据运算符的优先级结合性决定计算的顺序。控制语句分为条件语句循环语句跳转语句,在switch语句中,()里的值可以是byte、short、int、char、枚举字符串(后两者是对象类),case后的值是相应的常量表达式,for语句有"for-each"形式:for(type itr-val: collection) {…},对itr-val赋值不会影响collection中的值,break和continue都可以在后面添加label,这是针对嵌套循环进行设计的。
  • 数组是类类型,需要使用new语句创建数组:type arr-name[] = new type[size],数组的每个元素会自动初始化:0(数字型)(含字符型)、false(布尔型)或null(引用类型),也可以使用{,,}语句创建数组:type arr-name[] = {val1, val2, …, valn},可以创建数组的数组。字符串也是类类型,为String类,通常使用""语句创建字符串,String对象是不可变的,修改字符串要么重新创建,要么使用StringBuffer类。
  • Java是基于(Class)的,类是对象(Object)的模板,对象是类的实例,在Java文件中,主类的名称(MyClass)和文件的名称(MyClass.java)必须相同,类包括实例变量方法,实例变量和方法都叫类的成员,创建对象必须使用new语句,Java的对象引用与C/C++的内存指针本质上是一样的,对象引用变量的赋值不是拷贝,作为程序入口的类必须实现main()方法,方法还包括构造函数finalize()方法,构造函数用来初始化对象,构造函数的名字和类名相同,并且没有返回类型,其实隐式为该类,finalize()方法在对象销毁前释放某些资源(如关闭文件、断开网络连接等),Java不是在离开块时调用finalize()方法,而是在垃圾回收(Garbage Collection)时。重载方法的名字相同,但是参数列表(参数的类型,参数的个数,参数的顺序)必须不同,参数的类型不能完全匹配时,允许匹配可以自动类型转换的类型。static成员(static实例变量+static方法)本质上就是类的实例变量和方法,不是某个对象的实例变量和方法,可以用类直接访问静态成员,静态方法中只能使用静态实例变量和其他静态方法,静态实例变量可以在声明时初始化,也可以使用静态代码块(static {…})进行初始化。final静态变量是不可变的,可以在声明时初始化,也可以在构造函数中进行初始化。类可以像块一样嵌套,可以在类中定义类,只能在外部类中实例化内部类,也可以在块中定义类,也只能在块中使用内部类。
  • Java的继承(Inheritance)只支持单继承,子类不能访问父类的私有成员,self指代的是当前对象,super指代的是父类对象,可以使用super访问超类的实例变量和方法(包括构造函数),子类构造函数的第一条语句要么是super()方法,要么是this()方法,调用this()方法还是要首先调用super()方法,如果都没有,就会自动调用超类的默认构造函数,可见super()方法和this()方法不能同时使用。重写方法是指子类可以覆盖父类的方法,final变量不能修改,final方法不能重写,final类不能继承。父类变量可以引用子类变量,用该父类变量调用某个重写方法时,Java会在运行时根据指向对象的真正类型调用相应的重写方法,这就是运行时多态抽象类中包含抽象方法,当然也可以实现某些方法,不能实例化抽象类,所以抽象类中不能声明抽象构造函数,静态方法本质上是属于类的,所以抽象类也不能声明抽象静态方法,其实抽象类相对于实现类而言就是父类,所以抽象变量也可以像父类变量引用子类变量,
  • (Package)是类的容器,避免不同包的类名相同引发冲突,java文件的第一条语句是package语句,如果没有,会把类放入默认包中,Java使用文件系统目录存储包,根据目录的层级结构就可以创建层次化的包了,Java首先在当前工作目录中查找包,找不到的话再从CLASSPATH环境变量中的目录中查找,还找不到的话再看看javac/java指令中的-classpath选项指定的目录中有没有,如果还没有才会报错。完全限定名包括包名类名,使用import语句导入相关包或类,可以省略包名或类名,在import语句后面添加static关键字,可以导入类或接口的静态成员。Java的所有标准类都存储在java包中,Java编译器会自动导入java.lang子包:import java.lang.*。类成员的访问修饰符有public、protected和private,还有一种是默认的(无)(即无访问修饰符),与前三种都不同,public成员在包内、包外都可见,(无)只能在包内可见,protected在public与(无)之间,它比(无)多了一个“在其他包的子类中也可见”,private只能在类中可见。类和接口的访问控制只有两种:public和(无),规则跟类成员的public和(无)相同。
  • 与单个继承不同,一个类可以实现多个接口(Interface)。接口的所有成员都被隐式地声明为public,接口中的变量都是被隐式声明为finalstatic,而接口中的方法都只是抽象方法(只有;没有块),实现接口的类要么实现所有的接口方法,要么声明为abstract,当然实现接口的方法必须被声明为public。可以使用接口变量引用实现接口类的实例,接口可以像类一样继承,子接口可以扩展父接口,也可以像类一样嵌套,在接口中定义接口,内部接口的访问控制规则与类成员的相同,有public、protected、private和(无)。
  • 所谓的异常(Exception)就是运行时错误,可以在try块中抛出异常(throw),也可以让方法抛出异常(throws),可以捕获异常(catch)并进行相应的处理,也可以传递异常给外层try块或外部方法,让它们来进行处理,不论是否发生异常,都要执行finally块,finally块的功能类似finalize()方法,用来释放某些资源(如关闭文件、断开网络连接等),如果不想使用finally块,可以使用带资源的try语句
  • Java内置支持多线程(Multi-Thread),由于网络交互、文件读写、终端输入等IO操作要比CPU慢很多,我们可以采用异步操作的方式进行,如果希望多线程能够充分利用多核CPU,可以使用Fork/Join框架。可以通过两种方式自定义线程:一种是实现Runnable接口,实现里面的run()方法,另一种是继承Thread类,重写里面的run()方法,调用Thead.currentThead()方法可以获取主线程,所有子线程都源至主线程,因此主线程必须等到所有子线程结束了才能结束,可以使用join()方法等待子线程的结束,线程的常见状态有运行(running)、挂起(suspended)、恢复(resumed)和阻塞(blocked),线程的上下文切换基于协作式(自愿原则)和抢占式(优先原则)。为了避免竞态条件(Race Condition),Java还支持同步操作监视器(Monitor)的本质就是(Lock),Java的每个对象都有自己的隐式监视器,可以使用两种方法利用隐式监视器,一种是同步方法,一旦某个线程位于某个对象的某个同步方法中,其他线程就不能调用该对象的所有同步方法(只能调用非同步方法),另一种是同步语句:synchronized(target) {target.method(args)},可以对非同步方法进行同步操作。为了实现线程间更加细微的通信,还可以使用wait()方法notify()方法notifyAll()方法,为了避免一种叫“假唤醒”的小概率事件发生,Oracle推荐在一个检查线程等待条件的循环中调用wait()方法,我们不再使用suspend()方法、resume()方法和stop()方法来挂起、恢复和停止线程,这样会破坏基于隐式监视器的加锁机制,而是采用一种周期性检查的手工方式判断是否挂起、恢复和停止线程的执行。
  • Java的枚举是基于类的,枚举的变量和接口的变量一样,都是默认为public、static和final的,而且还是“自类型化的”(默认为所在的枚举类型),枚举虽然是类,但不能用new语句实例化,因为系统已经提供了相应的枚举常量,也不能继承其他类和被其他类继承,因为所有的枚举都自动继承了java.lang.Enum类并且final了自己,虽然如此,枚举也可以像其他类那样,提供实例变量和方法(包括构造函数),甚至实现接口。
  • java.io包中定义了基于(Stream)的I/O,java.nio及其子包中定义了基于缓冲(Buffer)和基于通道(Channel)的I/O,Java定义了两种类型的流:字节流(基于1个Byte)和字符流(基于2个Byte),字符流是建立在字节流的基础上的,字节流类系列的两个抽象类为InputStreamOutputStream,字符流类系列的两个抽象类为ReaderWriter,java.lang包中的System类包含了3个预定义的标准流:inouterr,in是InputStream类,out和err是PrintStream类,都属于字节流,可以使用BufferedReader类和PrintWriter类作为控制台I/O的字符流版本,读写文件可以使用FileInputStream类和FileOutputStream类。
  • 泛型就是参数化类型,就好比常量之于变量,类型之于泛型一样,有了泛型可以保证类型安全性类型参数可以有界:<T extends superClass>,也可以用通配符参数"?"指定未知类型,通配符参数也可以有界:<? extends superClass>和<? super subClass>(不包括subClass),不仅可以在泛型类中创建含有类型参数的泛型方法(包括泛型构造函数),还可以在非泛型类中创建泛型方法(<>在返回类型前),除了创建泛型类,还可以创建泛型接口,Java使用擦除实现了泛型,在运行时是没有类型参数的,所以使用泛型有一些限制:不能实例化类型参数,不能创建泛型的静态变量,静态方法的返回类型也不能是泛型,不能实例化泛型的数组,也不能创建特定类型的泛型的数组,更不能创建泛型异常类(不能继承Throwable类)。
  • Java也有lambda表达式,只是它的lambda表达式用起来很别扭,所以忽略之。