1、数组java
数组也是一种引用类型,其父类是Object,使用“数据类型[]”声明,如“int[] array”表示声明了一个元素类型为int类型的数组array。程序员
算法
// 静态初始化语法,即定义的时候就初始化好了全部的元素 int[] array1 = {100, 55, 30}; // 动态初始化语法,初始化时只定义好数组中元素的个数,new int[5]表示建立一个 // 有5个int类型元素的数组,可是并无初始化数组中元素的值,只是赋予了默认值,即 // 基本数据类型的默认值和引用类型的默认值null。 int[] array2 = new int[5];
使用数组时,应注意如下几点:数组
数组的访问和赋值:直接经过下标进行访问和赋值便可,如“array1[0]=22;”。工具
数组的优势和缺点:测试
数组扩容:Java中数组扩容的原理或者说方法是将小容量的数组使用“System.arraycopy”方法拷贝到大容量的数组当中,而后删除小容量的数组,Java中数组的扩容效率是较低的,因此在数组的使用当中,应该尽可能避免数组的拷贝和扩容。大数据
二维数组:二维数组,包括三位数组等多位数组,其实就是数组中的元素又是一个数组,多少维其实由这个数组的元素“套了多少层”决定的,二维就是数组中的元素是一个一维数组,同理,三位数组中的元素是一个二维数组,而后以此类推便可。spa
// 静态初始化语法 int[][] a = { {1, 2, 3}, {4, 5, 6}, {9} }; // 动态初始化语法 int[][] array = new int[3][4];
Arrays工具类:这个工具类最经常使用的就是sort和binarySearch这两个方法,可是注意,二分查找方法的前提是数组已经排好序了。code
import java.util.Arrays; public class ArrayToolsTest{ public static void main(String[] args){ int[] myArray = {3, 2, 6, 4}; // sort方法能够将一个数组排序,可是注意,sort方法并无返回值, // 即不是返回排好序的数组,而是直接排序传入的数组 Arrays.sort(myArray); // 二分查找算法的前提是须要数组已经排好序了 // 返回值为元素在数组中的下标,元素在数组中不存在则返回-1 // 可是这个方法多用来判断数组中有没有这个元素,由于若是数组中该元素 // 不仅一个的话,那么返回的下标不必定是第一个元素的下标 int indexd = Arrays.binarySearch(myArray, 6); } }
2、异常对象
一、对异常的理解
异常也是类,每个异常类均可以建立异常对象。
异常继承结构:经过帮助文档中能够看到,java.lang.Object --> java.lang.Throwable,而Throwable下有两个子类Error和Exception,它们都是能够抛出的,对于这两个子类分支,Error分支下的子类(包括Error自身)称之为错误,错误一旦发生,一般是直接就退出程序了,没有办法及时去处理。而Exception分支下的子类(包括Exception自身)称之为异常,异常是能够在代码层面提早去处理的,Exception的子类又能够分为两个分支,一个分支是RuntimeException及其子类,称为运行时异常,另外一个分支就是除RuntimeException外的其它Exception的直接子类,也称为编译时异常。
编译时异常:之因此称之为编译时异常,是由于在编译阶段就能够发现并提醒程序员提早处理这种异常,对于这类异常怎么提早去处理,仍是得要实际使用中多练才能有更深的体会。
运行时异常:这类异常在编译时不会报错,可是编译经过以后在运行时又会出错,因此叫运行时异常,好比对于表达式10/0,除数为0确定是错的,可是编译器并不会识别并提醒,编译经过以后运行的时候确定就会报错了。
异常处理:处理异常的方式有两种,一种是使用throws关键字和throw关键字,将异常抛出给上一级,让上一级去处理(上一级此时必须处理这个异常);另外一种是使用“try...catch”语句把异常捕获,可是注意,捕获到了这个异常不必定要去处理它,让它直接“过”也是容许的。
二、throws抛出异常
throws使用示例:
public class ThrowsTest{ public static void main(String[] args){ // 这里在编译时会发生错误,也就是编译时异常,之因此有这个异常 // 由于在func定义中有throws关键字,表示这个方法在执行过程当中可能会发生 // 对应的异常(ClassNotFoundException),因此它的上一级必须去处理 // 这个异常,不处理的话,编译器就会不经过。 func(); } // 使用throws关键字抛出可能发生的异常 public static void func() throws ClassNotFoundException{ System.out.println("my func!!!"); // 使用throw手动抛出一个异常 throw new ClassNotFoundException("未找到类异常!"); } }
关于throws的使用,须要注意:
三、try捕获异常
try使用示例:
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class ExceptionTest { public static void main(String[] args) { FileInputStream fis = null; try { // 将可能会发生异常的语句放在try的语句块中 // try语句块中的代码必定会去执行,直到发生异常为止 fis = new FileInputStream("Z:\\Study\\temp.md"); System.out.println(10 / 0); } catch (ArithmeticException e) { // 捕获可能会发生的异常 // 捕获到异常后,对异常进行处理 // catch语句块中的代码只有捕获到异常以后才会执行 // ArithmeticException e这个语句至关因而声明一种引用类型的变量,相似于方法的形参,e保存的是异常对象的内存地址,而且能够在catch语句块中去使用这个对象引用e。 System.out.println("发生算术异常!!!"); } catch (FileNotFoundException e) { // 可使用多个catch语句块捕获不一样的异常 // 多个catch时会从上到下依次捕获,执行了一个catch以后,其余的catch就不会执行了 // 而且多个catch语句时,应该遵循从上到下的“从小到大”捕获,即具体异常在前,它的父类型依次日后 System.out.println("文件不存在!!!"); } finally { // finally块中的语句不管是否发生异常都会处理,哪怕try块最后有个return语句 // 执行到return语句时也会先执行finally中的语句,再执行return // 能够用来处理一些不管是否发生异常都要处理的操做,如关闭文件流等 if (fis != null){ try{ fis.close(); } catch(IOException e) { e.printStackTrace(); } } System.out.println("关闭文件等其余操做。。。"); } } }
注意,catch捕获的异常能够是具体的异常,也能够是具体异常的父类型异常,此时能够理解为多态。
异常对象中的经常使用方法:
四、自定义异常
自定义的异常类须要继承Exception或者RuntimeException,而且须要定义无参和有参两个构造方法。
public class MyException extends Exception{ public MyException{ } public MyException(String s){ super(s); } }
自定义异常中的方法重写或者覆盖时须要注意一个语法问题,重写的方法抛出的异常不能比父类的方法更大或者说更宽泛,只能更小或者说更具体,好比父类异常方法抛出了IOException异常,那么异常子类中重写这个方法时就不能抛出Exception异常,可是能够抛出IOException异常或者FileNotFoundException异常。
3、泛型
泛型在使用尖括号“<标识符1,标识符2,...>”来表示,标识符表明的是某种类型。
泛型的做用实际上是用它定义了一个模板,定义时并无写死数据的类型,当真正使用的时候能够根据须要传入本身的数据类型。
自定义泛型:
/* 自定一个泛型只须要在类名以后使用<标识符>便可 注意,此处的标识符是随意定义,就像变量名同样 */ public class MyGenericTest<T> { public static void main(String[] args) { // 定义的时候,传入的类型是什么,那么建立的对象使用的泛型类型就是什么类型 MyGenericTest<String> mgt = new MyGenericTest<>(); mgt.func("自定义泛型方法测试!"); } /* 若是想要使用泛型定义的类型,在方法参数中直接使用便可 */ public void func(T t){ System.out.println(t); } }
集合中泛型的应用:
import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class GenericTest { public static void main(String[] args) { // 指定集合中的元素类型为Pet,不能存储其它类型的元素 // 使用new的时候能够不用再传入类型了,能够自动推断,此时的表达式<>也称为钻石表达式 // 若是不指定泛型,也是能够的,默认就是Object类型 List<Pet> petList = new ArrayList<>(); Cat c = new Cat(); Dog d = new Dog(); petList.add(c); petList.add(d); // 迭代器的声明也须要加上泛型的定义 Iterator<Pet> it = petList.iterator(); while (it.hasNext()) { // 本来next方法返回值的类型为Object,使用泛型以后返回的类型直接就是指定 // 的类型,不须要进行类型转换了。 Pet p = it.next(); p.play(); // 固然,若是要使用具体的子类对象的方法,仍是须要转型以后才能调用 if (p instanceof Cat){ Cat myCat = (Cat)p; myCat.sleep(); } if (p instanceof Dog){ Dog myDog = (Dog)p; myDog.bark(); } } /* 输出结果: 宠物在玩耍! 猫咪在睡觉! 宠物在玩耍! 狗子在嚎叫! */ } } class Pet { public void play() { System.out.println("宠物在玩耍!"); } } class Cat extends Pet { public void sleep() { System.out.println("猫咪在睡觉!"); } } class Dog extends Pet { public void bark() { System.out.println("狗子在嚎叫!"); } }