1、数组类型 静态初始化 Type[] arrayName ={element1,element2...} 动态初始化 arrayName =new type [length] 类和对象 定义类 各成员之间可以相互调用,但static修饰的成员不能访问没有static修饰的成员. 有static修饰的成员属于类本身,没有的成员属于该类的实例 调用static修饰的成员,用 类 作为主调 (即前面用类开头) 调用非static修饰的成员,用 this 作为主调(即前面用this开头) 方法详解 成员变量和局部变量 成员变量:类里定义的变量 (
2、包括实例变量,类变量) 局部变量:方法里定义的变量(包括形参,方法局部变量,代码块局部变量) 如果方法里的局部变量跟成员变量同名,局部变量会覆盖成员变量 如果需要这个方法里引用被覆盖的成员变量,则可使用this(对于实例变量)或类(对于类变量)作为调用者来限定访问成员变量。 使用访问控制符 Private 修饰成员变量最合适 Default 访问控制的成员或外部类可以被相同包下的其他类访问 Protected 成员即可以被同一个包中的其他类访问,也可以被不同包中的子类访问。通常是希望其子类来重写这个方法。 Public 可以被所有类访问。 (只有一些static
3、修饰的,类似全局变量的成员变量,才可能考虑使用public修饰) Package,import和import static Package 一组相关功能的类放在同一个package下 使用:在java源代码的第一个非注释行放置如下代码 package packageName; -d用于设置编译生成class文件的保存位置 -d. 代表当前路径 (同一个包中的类不必位于相同的目录下) 同一个包下的类可以自由访问,无须加包前缀 Import 用于导入制定包层次下的某个类或全部类 import package.subpackage.
4、ClassName; 导入某个类 import package.subpackage...*; 导入全部类 import static 静态导入用于导入指定类的单个或全部 静态成员变量,方法 import static package.subpackage...ClassName.fieldName|methodName; import static package.subpackage...ClassName.*; *使用import可以省略写包名 , 使用import static可以省略写类名 深入构造器 构造器里的this代表它
5、进行初始化的对象 构造器必须与类名相同 构造器不能直接被调用,构造器必须使用new关键字来调用 在构造器B中调用构造器A中的初始代码,可以使用this关键字来调用相应的构造器 使用this调用另一个重载的的构造器只能在构造器中使用,而且必须作为构造器执行体的第一条语句。 类的继承 继承的特点:子类不能获得父类的构造器 重写父类的方法 重写即子类把父类同名的方法覆盖 在子类方法中调用父类被覆盖的方法,则可以使用super或 父类类名 如果父类方法具有private访问权限,子类无法访问,无法重写 (super可以与this对比)
6、 多态 多态性 编译时类型是BaseClass,运行时类型是SubClass,就出现多态了。 多态简言之:BaseClass a = new SubClass() 编译类型 运行类型 引用变量时只能调用编译类型中具有的方法,但运行时执行它运行时类型所具有的方法 (父类有,子类有,方法用子类的 父类有,子类没,方法用父类的 父类没,子类有,编译失败) 对象的实例变量不具备多态性。因为通过引用变量来访问其包含的实例变量时,系统总是试图访问它编译时类型所定义的成员变量,而不是它运行时类型所定义的成员变量。 引用变量
7、的强制类型转换 引用变量只能调用它编译时类型的方法,而不能调用它运行时类型的方法。 如果试图把一个父类实例转换成子类类型,则这个对象必须实际上是子类实例才行(即编译时类型是父类类型,而运行时类型是子类类型) 继承与组合 使用继承的注意点 不希望子类重写该方法,用final修饰符 希望父类某个方法被子类重写,但不希望被其他类自由访问,用protected来修饰。 何时需要父类派生新的子类? 1. 子类需要额外增加属性,而不仅仅是属性的改变。 2. 子类需要增加自己的独有的行为方式。 利用组合实现复用 详见05\5.8\CompositeTest.java
8、书P154 继承表达的是一种“是”的关系,组合表达的是一种“有”的关系 初始化块 使用初始化块 初始化块要么不带任何修饰符,要带修饰符只能带static。 初始化顺序:先执行初始化块或声明实例变量时指定的初始值; 再执行构造器里指定的初始值 初始化块和构造器 与构造器不同,初始化快是一段固定执行的代码,它不能接收任何参数。 静态初始化块 静态初始化块不能对实例变量进行初始化处理 (普通初始化块负责对对象执行初始化,静态初始化块负责对类进行初始化) 处理对象 toString方法 toString方法总是返回该对象
9、实现类的“类名+@+hashCode”值,但这个描述不能真正实现自我描述,因此如果用户需要自定义类能实现自我描述,就必须重写Object类的toString方法。 ==和equals方法 当使用==来判断两个变量是否相等时,如果 两个变量是基本类型变量,且都是数值型,只要两个变量的值相等 ,就返回true;但如果是两个引用类型变量,只要它们指向同一个对象,==判断才会返回true。(Object类中equals与==没区别,所以需要重写) String重写了Object的equals方法,只要两个字符串所包含的字符序列相同,就返回true。 详见P170 final修饰符
10、final成员变量 Final修饰的成员变量必须由程序员显示的指定初始值 Final修饰的实例变量,在普通初始化块或构造器中指定初始值; Final修饰的类变量,在定义静态初始块或定义该类变量时指定初始值。 final方法和类 Final修饰的方法不能被重写,但可以被重载; Final修饰的类不可以有子类; 抽象类 抽象方法和抽象类 有抽象方法的类只能被定义成抽象类,抽象类里可以没有抽象方法; 抽象类不能被实例化; 抽象类的构造器不能用于创建实例,主要用于被其子类调用; Abstract修饰类,表明该类只能被继承 Abstract修饰方法,表明
11、该方法必须由子类重写 Abstract不能修饰成员变量,局部变量,构造器 接口 接口的定义 接口定义的基本语法 [修饰符]interface 接口名 extends 父接口1,父接口2... { 零个到多个常量定义... 零个到多个抽象方法定义... 零个到多个内部类,接口,枚举定义... 零个到多个默认方法或类方法定义... } 接口里的方法都是抽象方法 一个接口可以有多个直接父接口,但接口只能继承接口,不能继承类 接口里可以包含 成员变量:只能是静态常量 方法:实例方法,类方法,默认方法 内部类:内部接口,枚举 定义接口成员
12、时,可以省略访问控制修饰符,如果要指定,只能是public 常量默认 public static final修饰 方法默认 public abstract修饰 使用接口 实现接口的语法格式 [修饰符]class 类名 extends 父类 implements 接口1,接口2... { 类体部分 } 一个类实现了一个或多个接口后,这个类必须完全实现这些接口里定义的全部抽象方法; 否则,该类将保留从父类接口哪里继承到的抽象方法,该类也必须定义成抽象类; 一个类实现某个接口时,会获得接口中定义的常量,方法等 注:实现接口方法时,必须使用public
13、修饰,因为接口里的方法都是public的,而子类重写父类方法时访问权限只能更大或相等 接口和抽象类 接口和抽象类都不能被实例化; 接口和抽象类都可以包含抽象方法; 接口与抽象类的差别详见P195 内部类 内部类成员可以直接访问外部类的私有数据 内部类比外部类多三个修饰符 private ,protected,static 非静态内部类不能拥有静态成员 非静态内部类 public class Outer { private int outProp = 9; class Inner { private int in
14、Prop = 5; public void acessOuterProp() { //内部类可以直接访问外部类的成员 System.out.println("外部类的outProp属性值:" + outProp); } } public void accessInnerProp() { //外部类不能直接访问内部类属性,下面代码出现编译错误 //System.out.println("内部类的inProp属性值:" + inProp); //如需访问内部类成员,必须显式创建内部类对象 System.out.println("
15、内部类的inProp属性值:" + new Inner().inProp); } public static void main(String[] args) { //执行下面代码,只创建了外部类对象,还未创建内部类对象 Outer out = new Outer(); Inner in =new Inner(); System.out.println("内部类的inProp属性值:" +out.this.inProp); } } 静态内部类 用static修饰后,内部类就属于外部类本身,而不是外部类的某个对象了。 使用内部类
16、 1在外部类使用内部类 直接通过内部类的类名来定义变量 通过new调用内部类构造器来创建实例 2在外部类以外来使用非静态内部类 在外部类以外的地方定义内部类 OuterClass.InnerClass varName 在外部类以外的地方创建非静态内部类实例 OuterInstance.new InnerConstructor() 实例 构造器 3在外部类以外使用静态内部类 因为静态内部类是外部类类相关的,所以创建静态内部类实例的语法如下 new OuterClass.InnerConstrutor() 匿名内部类 匿名内部类适合创建那种
17、只需要一次使用的类 匿名内部类必须也只能继承一个父类,或实现一个接口 两条规则 1匿名内部类不能使抽象类 2匿名内部类不能定义构造器。因为匿名内部类没有类名,所以无法定义构造器 枚举类 继承的是java.lang.Enum类 非抽象的枚举类默认使用final修饰,所以不能派生子类 构造器默认private修饰 单例模式 单例模式的两种写法 /* 这个是先初始化对象。 称为:饿汉式。 Single类一进内存,就已经创建好了对象。 class Single { private static Single s = new Single(); pri
18、vate Single(){} public static Single getInstance() { return s; } } */ //对象是方法被调用时,才初始化,也叫做对象的延时加载。成为:懒汉式。 //Single类进内存,对象还没有存在,只有调用了getInstance方法时,才建立对象。 class Single { private static Single s = null; private Single(){} public static Single getInstance() { if(s==null) {`
19、 synchronized(Single.class) { if(s==null) s = new Single(); } } return s; } } //记录原则:定义单例,建议使用饿汉式。 异常 异常体系: Throwable |--Error |--Exception |--RuntimeException 异常体系的特点: 异常体系中的所有类以及建立的对象都具备可抛性。 也就是说可以被throw和throws关键字所操作。 只有异常体系具备这个特点。
20、 -------------- throw和throws的用法: throw定义在函数内,用于抛出异常对象。 throws定义在函数上,用于抛出异常类,可以抛出多个用逗号隔开。 当函数内容有throw抛出异常对象,并未进行try处理。必须要在函数上声明,都在编译失败。 注意,RuntimeException除外。也就说,函数内如果抛出的RuntimeExcpetion异常,函数上可以不用声明。 -------------- 如果函数声明了异常,调用者需要进行处理。处理方法可以throws可以try。 异常有两种: 编译时被检测异常 该
21、异常在编译时,如果没有处理(没有抛也没有try),编译失败。 该异常被标识,代表这可以被处理。 运行时异常(编译时不检测) 在编译时,不需要处理,编译器不检查。 该异常的发生,建议不处理,让程序停止。需要对代码进行修正。 -------------- 异常处理语句: try { 需要被检测的代码; } catch () { 处理异常的代码; } finally { 一定会执行的代码; } 有三个结合格式: 1. try { } catch () { } 2. try {
22、 } finally { } 3. try { } catch () { } finally { } 注意: 1,finally中定义的通常是 关闭资源代码。因为资源必须释放。 2,finally只有一种情况不会执行。当执行到System.exit(0);fianlly不会执行。 -------------- 自定义异常: 定义类继承Exception或者RuntimeException 1,为了让该自定义类具备可抛性。 2,让该类具备操作异常的共性方法。 当要定义自定义
23、异常的信息时,可以使用父类已经定义好的功能。 异常异常信息传递给父类的构造函数。 class MyException extends Exception { MyException(String message) { super(message); } } 自定义异常:按照java的面向对象思想,将程序中出现的特有问题进行封装。 -------------- 异常的好处: 1,将问题进行封装。 2,将正常流程代码和问题处理代码相分离,方便于阅读。 异常的处理原则: 1,处理方式有两种:try 或者 throws。
24、 2,调用到抛出异常的功能时,抛出几个,就处理几个。 一个try对应多个catch。 3,多个catch,父类的catch放到最下面。 4,catch内,需要定义针对性的处理方式。不要简单的定义printStackTrace,输出语句。 也不要不写。 当捕获到的异常,本功能处理不了时,可以继续在catch中抛出。 try { throw new AException(); } catch (AException e) { throw e; } 如果该异常处理不了,但并不属于该功能出现的异常。 可以
25、将异常转换后,再抛出和该功能相关的异常。 或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去, 当调用者知道。并处理。也可以将捕获异常处理后,转换新的异常。 try { throw new AException(); } catch (AException e) { // 对AException处理。 throw new BException(); } 异常的注意事项: 在子父类覆盖时: 1,子类抛出的异常必须是父类的异常的子类或者子集。 2,如果父类或者接口没有异常抛出时,子类覆盖
26、出现异常,只能try不能抛。 String String类适用于描述字符串事物。 那么它就提供了多个方法对字符串进行操作。 常见的操作有哪些? 1,获取。 1.1 字符串中的包含的字符数,也就是字符串的长度。 int length():获取长度。 1.2 根据位置获取位置上某个字符。 char charAt(int index): 1.3 根据字符获取该字符在字符串中位置。 int indexOf(int ch):返回的是ch在字符串中第一次出现的位置。 int indexOf(int ch, int fromIndex) :从fr
27、omIndex指定位置开始,获取ch在字符串中出现的位置。 int indexOf(String str):返回的是str在字符串中第一次出现的位置。 int indexOf(String str, int fromIndex) :从fromIndex指定位置开始,获取str在字符串中出现的位置。 int lastIndexOf(int ch) : 2,判断。 2.1 字符串中是否包含某一个子串。 boolean contains(str): 特殊之处:indexOf(str):可以索引str第一次出现位置,如果返回-1.表示该str不在
28、字符串中存在。 所以,也可以用于对指定判断是否包含。 if(str.indexOf("aa")!=-1) 而且该方法即可以判断,有可以获取出现的位置。 2.2 字符中是否有内容。 boolean isEmpty(): 原理就是判断长度是否为0. 2.3 字符串是否是以指定内容开头。 boolean startsWith(str); 2.4 字符串是否是以指定内容结尾。 boolean endsWith(str); 2.5 判断字符串内容是否相同。复写了Object类中的equals方法。 boolean equal
29、s(str); 2.6 判断内容是否相同,并忽略大小写。 boolean equalsIgnoreCase(); 3,转换。 3.1 将字符数组转成字符串。 构造函数:String(char[]) String(char[],offset,count):将字符数组中的一部分转成字符串。 静态方法: static String copyValueOf(char[]); static String copyValueOf(char[] data, int offset, int count) static St
30、ring valueOf(char[]): 3.2 将字符串转成字符数组。** char[] toCharArray(): 3.3 将字节数组转成字符串。 String(byte[]) String(byte[],offset,count):将字节数组中的一部分转成字符串。 3.4 将字符串转成字节数组。 byte[] getBytes(): 3.5 将基本数据类型转成字符串。 static String valueOf(int) static String valueOf(double) //3+"";
31、//String.valueOf(3); 特殊:字符串和字节数组在转换过程中,是可以指定编码表的。 4,替换 String replace(oldchar,newchar); 5,切割 String[] split(regex); 6,子串。获取字符串中的一部分。 String substring(begin); String substring(begin,end); 7,转换,去除空格,比较。 7.1 将字符串转成大写或则小写。 String toUpperCase(); String toLowerCase();
32、 7.2 将字符串两端的多个空格去除。 String trim(); 7.3 对两个字符串进行自然顺序的比较。 int compareTo(string); StringBuffer StringBuffer是字符串缓冲区。 是一个容器。 特点: 1,长度是可变化的。 2,可以字节操作多个数据类型。 3,最终会通过toString方法变成字符串。 C create U update R read D delete 1,存储。 StringBuffer append():将指定数据作为参数添加到已有数据结尾处。 String
33、Buffer insert(index,数据):可以将数据插入到指定index位置。 2,删除。 StringBuffer delete(start,end):删除缓冲区中的数据,包含start,不包含end。 StringBuffer deleteCharAt(index):删除指定位置的字符。 3,获取。 char charAt(int index) int indexOf(String str) int lastIndexOf(String str) int length() String substring(int start, i
34、nt end) 4,修改。 StringBuffer replace(start,end,string); void setCharAt(int index, char ch) ; 5,反转。 StringBuffer reverse(); 6,将缓冲区中指定数据存储到指定字符数组中。 void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) JDK1.5 版本之后出现了StringBuilder. StringBuffer是线程同步。 StringBui
35、lder是线程不同步。 以后开发,建议使用StringBuilder 升级三个因素: 1,提高效率。 2,简化书写。 3,提高安全性。 基本数据类型对象包装类。 Byte Byte Short short int Integer long Long boolean Boolean Float Float double Double char Character 基本数据类型对象包装类的最常见作用, 就是用于基本数据类型和字符串类型之间做转换 基本数据类型转成字符串。 基本数据类型+"" 基本数据
36、类型.toString(基本数据类型值); 如: Integer.toString(34);//将34整数变成"34"; 字符串转成基本数据类型。 xxx a = Xxx.parseXxx(String); int a = Integer.parseInt("123"); double b = Double.parseDouble("12.23"); boolean b = Boolean.parseBoolean("true"); Integer i = new Integer("123"); int num = i.intV
37、alue(); 十进制转成其他进制。 toBinaryString(); toHexString(); toOctalString(); 其他进制转成十进制。 parseInt(string,radix); 集合 Collection |--List:元素是有序的,元素可以重复。因为该集合体系有索引。 |--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。 |--LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。 |--Vector
38、底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低。 |--Set:元素是无序,元素不可以重复 Collection定义了集合框架的共性功能。 1,添加 add(e); addAll(collection); 2,删除 remove(e); removeAll(collection); clear(); 3,判断。 contains(e); isEmpty(); 4,获取 iterator(); size(); 5,获取交集。 retainAll(); 6,集合变数组。 toArr
39、ay(); 1,add方法的参数类型是Object。以便于接收任意类型对象。 2,集合中存储的都是对象的引用(地址) 什么是迭代器呢? 其实就是集合的取出元素的方式。 如同抓娃娃游戏机中的夹子。 迭代器是取出方式,会直接访问集合中的元素。 所以将迭代器通过内部类的形式来进行描述。 通过容器的iterator()方法获取该内部类的对象。 List: 特有方法。凡是可以操作角标的方法都是该体系特有的方法。 增 add(index,element); addAll(index,Collection); 删 remove(ind
40、ex); 改 set(index,element); 查 get(index): subList(from,to);//包含头元素,不包含尾元素 listIterator(); int indexOf(obj):获取指定元素的位置。 ListIterator listIterator(); List集合特有的迭代器。ListIterator是Iterator的子接口。 在迭代时,不可以通过集合对象的方法操作集合中的元素。 因为会发生ConcurrentModificationException异常。 所以,在迭代器时,只能用迭
41、代器的放过操作元素,可是Iterator方法是有限的, 只能对元素进行判断,取出,删除的操作, 如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。 该接口只能通过List集合的listIterator方法获取。 LinkedList:特有方法: addFirst(); addLast(); getFirst(); getLast(); 获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException removeFirst(); removeLast(); 获取元素,但是元素被删除。如果集合
42、中没有元素,会出现NoSuchElementException 在JDK1.6出现了替代方法。/////以后用这个 offerFirst(); offerLast(); 添加元素 peekFirst(); peekLast(); 获取元素,但不删除元素。如果集合中没有元素,会返回null。 pollFirst(); pollLast(); 获取元素,但是元素被删除。如果集合中没有元素,会返回null。 List集合判断元素是否相同,依据是元素的equals方法。 Set Set集合的功能和Collection是一致的。 |--Set:元素
43、是无序(存入和取出的顺序不一定一致),元素不可以重复。、 HashSet 底层数据结构是哈希表。是线程不安全的。不同步。 HashSet是如何保证元素唯一性的呢? 是通过元素的两个方法,hashCode和equals来完成。 如果元素的HashCode值相同,才会判断equals是否为true。 如果元素的hashcode值不同,不会调用equals。 注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。 TreeSet 可以对Set集合中的元素进行排序。 记住,排序时,当主要条件相同时,
44、一定判断一下次要条件 底层数据结构是二叉树。 保证元素唯一性的依据: compareTo方法return 0. TreeSet排序的第一种方式:让元素自身具备比较性。 元素需要实现Comparable接口,覆盖compareTo方法。 也种方式也成为元素的自然顺序,或者叫做默认顺序。 TreeSet的第二种排序方式。 当元素自身不具备比较性时,或者具备的比较性不是所需要的。 这时就需要让集合自身具备比较性。 在集合初始化时,就有了比较方式。 当元素自身不具备比较性,或者具备的比
45、较性不是所需要的。 这时需要让容器自身具备比较性。 定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。 当两种排序都存在时,以比较器为主。 定义一个类,实现Comparator接口,覆盖compare方法。 Map Map集合 :该集合存储键值对。一对一对往里存。而且要保证键的唯一性。 1,添加。 put(K key, V value) ///第一次赋值,第二次如果键相同,则覆盖 putAll(Map extends K,? extends V> m) 2,删除。 clear() remove(
46、Object key) 3,判断。 containsValue(Object value) containsKey(Object key) isEmpty() 4,获取。 get(Object key) size() values() entrySet() keySet() Map |--Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。jdk1.0.效率低。 |--HashMap:底层是哈希表数据结构,允许使用 null 值和 null 键,该集
47、合是不同步的。将hashtable替代,jdk1.2.效率高。
|--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。
和Set很像。其实Set底层就是使用了Map集合。
map集合取出的两种方式
代码示例见day16 MapDemo2
1,Set 48、v>> entrySet:将map集合中的映射关系存入到了set集合中,
而这个关系的数据类型就是:Map.Entry
Entry其实就是Map中的一个static内部接口。
为什么要定义在内部呢?
因为只有有了Map集合,有了键值对,才会有键值的映射关系。
关系属于Map集合中的一个内部事物。
而且该事物在直接访问Map集合中的元素。
Map.Entry 其实Entry也是一个接口,它是Map接口中的一个内部接口。
Collections
Collections:集合框架的工具类。里面定义的都是静态方法。
49、
Collections和Collection有什么区别?
Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。
它有两个常用的子接口,
List:对元素都有定义索引。有序的。可以重复元素。
Set:不可以重复元素。无序。
Collections是集合框架中的一个工具类。该类中的方法都是静态的
提供的方法中有可以对list集合进行排序,二分查找等方法。
通常常用的集合都是线程不安全的。因为要提高效率。
如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。
集合变数组。
Coll 50、ection接口中的toArray方法。
1,指定类型的数组到底要定义多长呢?
当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组。长度为集合的size。
当指定类型的数组长度大于了集合的size,就不会新创建了数组。而是使用传递进来的数组。
所以创建一个刚刚好的数组最优。
String[] arr = al.toArray(new String[al.size()]);
2,为什么要将集合变数组?
为了限定对元素的操作。不需要进行增删了。
Arrays:
用于操作数组的工具类。里面都是静态方法。
asList:将数组






