重点归纳 要产生对象必须先定义类,类是对象的设计图,对象是类的实例。类定义时使用cas关键词,建立实例要使用new关键词。以类名称声明的变量,称为参考名称、参考变量或直接叫参考 想在建立对象时,一并进行某个初始流程,像是指定数据成员值,则可以定义构造函数,构造函数是与类名称同名的方法。参数名称与对象数据成员同名时,可以在数据成员前使用this区别. java.util. Scanner的 nextint方法会看看标准输入中,有没有输入下一个字符串(以空格或换行分隔),有的话会尝试将之剖析为int类型,其他还有 nextByte()、 nextShort()、nextLong()nextFloat()、nextDouble()、snextBoolean()如果直接取得上一个字符串则使用next(),如果想取得用户输入的整行文字,则使用 nextline()(以换行分隔)。 Java(包括其他程序语言)遵守EEE754浮点数运算规范,使用分数与指数来表示浮点数。如果要求精确度,那就要小心使用浮点数,而且别用一直接比较浮点数运算结果。可以使用java.math. BigDecimal类得到想要的精确度 =是用在指定参考名称参考某个对象,而==是用在比较两个参考名称是否参考同一对象要让基本类型像对象一样操作,可以使用 Long、 Integer、 Double、 Float、 Boolean、Byte等类来打包基本类型,这些类就是所谓的打包器。除了使用new创建基本类型打包器之外,从J2SE5.0之后提供了自动装箱功能。自动装箱与拆箱的功能事实上是编译程序蜜糖。 数组在Java中就是对象,索引由0开始,存取超出索引范围,就会抛出 Arrayindexoutofboundsexception错误。从JDK5之后,有了更方便的增强式for循环语法可用于循序取得数组元素。使用new建立数组后,每个索引元素会有默认值类默认值是null。在Java中,数组一旦建立,长度就固定了。 无论 System. arraycopy还是 Arrays..copyOf(),用在类类型声明的数组时,都是执行浅层复制. 字符串本质是打包字符数组的对象,是java.lang. String类的实例。在启动JVM并指定执行类时,可以一并指定命令行自变量,会收集为 string数组,由main()中的args参考,以""包括的字符串,只要内容相同(序列、大小写相同),无论在程序代码中出现几次,JVM都只会建立一个 String实例,并在字符串池中维护。如果想比较字符串实际字符内容是否相同,不要使用==,要使用 equals(). 字符串对象一旦建立,就无法更改对象中任何内容,对象上没有任何方法可以更改字符串内容。使用+连接字符串会产生新的 String实例,不要将+用在重复性的连接场合。 使用 Javac指令没有指定-encoding选项时,会使用操作系统默认编码.
构造函数实现对象初始化流程的封装。方法封装了操作对象的流程。Java中还可以使用 private封装对象私有数据成员。封装的目的主要就是隐藏对象细节,将对象当作黑箱进行操作。 在Java命名规范中,取值方法的名称形式是固定的,也就是以get开头,之后接上首字母大写的单词。 如果没有声明权限修饰的成员,只有在相同的类程序代码中才可以直接存取,也就是“包范围权限”。如果想在其他包的类程序代码中存取某包的类或对象成员,则该类或对象成员必须是公开成员,在Java中要使用 public加以声明 创建对象时,数据成员就会初始化,如果没有指定初始值,则会使用默认值初始化。如果定义类时,没有撰写任何构造函数,编译程序会自动加入一个无参数、内容为空的构造函数,称为默认构造函数。可以定义多个构造函数,只要参数类型或个数不同,这称为重载构造函数 定义方法时也可以进行重载,可为类似功能的方法提供统一名称,但根据参数类型或个数的不同调用对应的方法。 编译程序在处理重载方法时,会依以下顺序来处理: 1)还没有装箱动作前可符合自变量个数与类型的方法。 2)装箱动作后可符合自变量个数与类型的方法 3)尝试有不定长度自变量并可符合自变量类型的方法 4)找不到合适的方法,编译错误 除了被声明为 static的地方外,this关键字可以出现在类中任何地方,在对象建立后为“这个对象”的参考名称。this()代表了调用另一个构造函数,至于调用哪个构造函数,则视调用this()时给的自变量类型与个数而定 如果对象数据成员被声明为final,但没有明确使用指定值,那表示延迟对象成员值的指定,在构造函数执行流程中,一定要有对该数据成员指定值的动作,否则编译错误。被声明为 static的成员,不会让个别对象拥有,而是属于类 Java程序设计领域,早就有许多良好命名习惯,没有遵守习惯并不是错,但会造成沟通与维护的麻烦。以类命名实例来说,首母是大写,以 static使用习惯来说,是通过类名称与“”运算符来存取。在大家都遵守命名习惯的情况下,看到首字母大写就知道它是类,通过类名称与“”运算符来存取,就会知道它是 static成员。 在 static方法或区块中不能出现this关键字 static方法中不能用非 static数据或方法成员。 import static语法是为了偷懒,但别偷懒过头,要注意名称冲突问题,有些名称冲突编译程序可通过以下顺序来解析。 1、局部变量覆盖:选用方法中的同名变量、参数、方法名称 2、成员覆盖:选用类中定义的同名数据成员、方法名称 3、重载方法比较:使用 import static的各个静成员,若有同名冲突,尝试通过重载判断 在JDK5之后支持不定长度自变量,为编译程序蜜糖,展开后变为数组。使用不定长度自变量时,方法上声明的不定长度参数必是参数列最后一个,使用两个以上不定长度自变量也是不合法的。
接口与多态 对于“定义行为”,可以使用 interface关键字定义,接口中的方法不能操作,直接标示为abstract,而且一定是 public。类要操作接口,必须使用 implements关键字。操作某 abstract接口时,对接口中定义的方法有两种处理方式,一是操作接口中定义的方法,二是再度将该方法标示为 abstract。 以Java的语意来说,继承会有“是一种”关系,操作接口则表示“拥有行为”,但不会有“是一种”的关系。对于接口多态语法的断,方式是“右边是不是拥有左边的行为”,或者“右边对象是不是操作了左边接口” 类可以操作两个以上的类,也就是拥有两种上的行为。类可以同时继承某个类,并操作某些接口。接口可以继承自另一个接,也就是继承父接口行为,再在子接口中额外定义行为 使用 interface来定义抽象的行为外观,方法要声明为 public abstract,无须且不能有操作。为了方便,也可以省略 public abstract,编译程序会协助补齐 可以使用接口枚举常数,只能定义为 public static final。为了方便, public static final可以省略,编译程序会协助补齐 如果有两个接口都定义了某方法,操作两个接口的类并不会有错误,照样通过编译但在设计上要思考一下:两个接口都有定义的方法是否表示不同的行为? 接口可以继承别的接口,也可以同时继承两个上的接口,同样也是使用 extends关键字,这代表了继承父接口的行为。 如果有临时继承某个类或操作某个接口并建立实例的需求,而这类子类或接口操作类只使用一次,不需要为这些类定义名称,这时可以使用匿名内部类来解决这个需求。匿名内部类的语法为: new父类()接口(){ //类本体操作 从JK5之后新增了enum语法,可用于定义枚举常数。enum定义了特殊的类,继承自java.lang.Enum,不过这是由编译程序处理,直接撰写程序继承Enum类会被编译程序拒绝eum实际上定义了类,而enum中列举的常数,实际上是public static final,且为枚举类型实例,无法撰写程序直接实例化枚举类型,因为构造函数权限设定为 private,只有类中才可以实例化。
异常处理
java中所有错误都会被包装为对象,如果你愿意,可以尝试(try)执行程序并捕捉(cat代表错误的对象后做一些处理。使用了try、cath语法,JVM会尝试执行try区块中的程序代码,如果发生错误,执行流程会跳离错误发点,然后比对 catch括号中声明的类型是否符合被抛出的错误对象类型,如果是的话就执行 catch区块中的程序代码
错误会被包装为对象,这些对象都是可抛出的,因此设计错误对象都继承自 java.lang.Throwable类, Throwable定义了取得错误信息、堆栈追踪( Stack Trace)等方法,它有两个子类:java.lang. Error与java.lang. Exception
Eor与其子类实例代表严重系统错误,例如件层面错误、JVM错误或内存不足等问题。虽然也可以使用try、 catch来处理Eror对象,但并不建议,发生严重系统错误时,Jva应用程序本身是无力处理的。
如果抛出了 Throwable对象,而程序中没有任何 catch捕捉到错误对象,最后由JVM捕捉到的话,那JVM基本处理就是显示错误对象包装的信息并中断程序
程序设计本身的错误,建议使用 Exception或其子类实例来表现,所以通常称错误处理为异常处理( Exception Handling)。单就语法与继承架构上来说,如果某个方法声明会抛出 Throwable.或子类实例,只要不是属于 Error或
java. lang .Runtimeexception或其子类实例,你就必须明确使用try、catch语法加以处理,或者在方法中用 throws声明这个方法会抛出异常,否则会编译失败 Exception或其子对象,但非属于 Runtimeexception或其子对象,称为受检异常(Checked Exception),受谁检查?受编译程序检查!受检异常存在的目的,在于API设计者实现某方法时,某些条件成立时会引发错误,而且认为调用方法的客户端有能力处理错误,要求编译程序提醒客户端必须明确处理错误,不然不可通过编译,API客户端无权选择要不要处理。
属于Runtimeexception衍生出来的类实例,代表API设计者实现某方法时,某些条件成立时会引发错误,而且认为API客户端应该在调用方法前做好检查,以避免引发错误之所以命名为执行时期异常,是因为编译程序不会强迫一定得在语法上加以处理,亦称为非受检异常( Unchecked Exception)
如果父类异常对象在子类异常对象前被捕捉,则 catch子类异常对象的区块将永远不会被执行,编译程序会检查出这个错误。从DK7开始,可以使用多重捕捉( multi-catch)语法,不过仍得注意异常的继承, catch括号中列出的异常不得有继承关系,否则会发生编译错误
操作对象的过程中如果会抛出受检异常,但目前境信息不足以处理异常,所以无法使用try、 catch处理时,可由方法的客户端依据当时调用的环境信息进行处理。为了告诉编译程序这个事实,必须使用 throws声明此方法会抛出的异常类型或父类型,编译程序才会让你通过编译
如果是非受检异常,原本就可以自行选择是否处理常,因此不使用try、cach处理时也不用特别在方法上使用 thtows声明,不处理非受检异常时,异常会自动往外传播。
在 catch区块进行完部分错误处理之后,可以使用 throw(注意不是 throws)将异常再抛出。在JDK7中,编译程序对于重新抛出的异类型可以更精准判断。
若想得知异常发生的根源,以及多重方法调用下异常的堆栈传播,可以利用异常对象自动收集的堆栈追踪来取得相关信息,例如调用异常对象的 printstacktrace、 getstacktrace()等方法。
要善用堆栈追踪,前提是程序代码中不可有私吞异常的行为、对异常做了不适当的处理,或显示了不正确的信息
在使用 throw重抛异常时,异常的追踪堆栈起点,仍是异常的发生根源,而不是重抛异常的地方。如果想要让异常堆栈起点为重抛异常的地方,可以使用fillInStackTrace(),这个方法会重新装填异常堆栈,将起点设为重抛异常的地方,并返回 Throwable对象无论try区块中有无发生异常,若撰写有 finally区块,则 finally区块一定会被执行如果程序撰写的流程中先 return了,而且也有 finally区块, finally区块会先执行完后,再将值返回。
在JDK7之后,新增了尝试关闭资源( try-with- Resources)语法,想要尝试自动关闭资源的对象,是撰写在try之后的括号中。
若一个异常被 catch/后的处理过程引发另一个异常,通常会抛出第一个异常作为响应 addsuppressed(方法是JDK7在java, lang Throwable中新增的方法,可将第二个异常记录在第一个异常之中,JDK7中与之相对应的是 getsuppressed()方法,可返回 Throwable,代表先前被 addsuppressed()记录的各个异常对象
JDK7的尝试关闭资源语法可套用的对象,必须操作java.ang. Autocloseable接口,这是JDK7新增的接口。尝试关闭资源语法也可以同时关闭两个以上的对象资源,只要中间以分号分隔。在try的括号中,越后面撰写的对象资源会越早被关闭。