java
1、访问控制和继承
请注意以下方法继承的规则:
-
父类中声明为 public 的方法在子类中也必须为 public。
-
父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public,不能声明为 private。
-
父类中声明为 private 的方法,不能够被继承。
非访问修饰符
为了实现一些其他的功能,Java 也提供了许多非访问修饰符。
static 修饰符,用来修饰类方法和类变量。 static 关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量。
final 修饰符,用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。
abstract 修饰符,用来创建抽象类和抽象方法。 如果一个类包含抽象方法,那么该类一定要声明为抽象类。 任何继承抽象类的子类必须实现父类的所有抽象方法,除非该子类也是抽象类。
synchronized 和 volatile 修饰符,主要用于线程的编程。
2、包装类
Number类属于java.lang包;
这种由编译器特别支持的包装称为装箱,所以当内置数据类型被当作对象使用的时候,编译器会把内置类型装箱为包装类。相似的,编译器也可以把一个对象拆箱为内置类型。
作用:
作为和基本数据类型对应的类 类型存在,方便涉及到对象的操作。
包含每种基本数据类型的相关属性如最大值、最小值等,以及相关的操作方法。
int n=5;
Integer n1=new Integer(n);
System.out.println("int类型转换为integer类:"+n1);
//
Integer i=new Integer(50);
int i1 = i.intValue();
System.out.println("integer类转换为int类型:"+i1);
3、String类/StringBuffer类/StringBuilder类
字符串广泛应用 在 Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串。 String 创建的字符串存储在公共池中,而 new 创建的字符串对象在堆上。
String s1 = "Runoob"; // String 直接创建
String s2 = "Runoob"; // String 直接创建
String s3 = s1; // 相同引用
String s4 = new String("Runoob"); // String 对象创建
String s5 = new String("Runoob"); // String 对象创建
String 类是不可改变的,所以你一旦创建了 String 对象,那它的值就无法改变了。
如果需要对字符串做很多修改,那么应该选择使用 StringBuffer & StringBuilder 类。
String类的常用方法:
方法 | 描述 |
---|---|
char charAt(int index) | 返回指定索引处的 char 值。 |
int compareTo(Object o) | 把这个字符串和另一个对象比较。 |
int compareTo(String s) | 按字典顺序比较两个字符串。 |
int compareToIgnoreCase(String s) | 按字典顺序比较两个字符串,不考虑大小写。 |
String concat(String s) | 将指定字符串连接到此字符串的结尾。 |
boolean contentEquals(StringBuffer sb) | 当且仅当字符串与指定的StringBuffer有相同顺序的字符时候返回真。 |
static String copyValueOf(char[] data, int offset, int count) | 返回指定数组中表示该字符序列的 String。 |
boolean endswith(String s) | 测试此字符串是否以指定的后缀结束。 |
boolean startsWith(String s) | 测试此字符串是否以指定的前缀开始。 |
boolean equals(Object o) | 将此字符串与指定的对象比较。。 |
isEmpty() | 判断字符串是否为空。 |
contains(CharSequence chars) | 判断是否包含指定的字符系列。 |
String toString() | 返回对象本身。 |
String toLowerCase()/toUpperCase() | 使用默认语言环境的规则将此 String 中的所有字符都转换为小写/大写。 |
char[] toCharArray() | 将此字符串转换为一个新的字符数组。 |
int indexOf(char ch)/(String s) | 返回指定字符在此字符串中第一次出现处的索引。 |
int lastIndexOf(char ch)/(String s) | 返回指定字符在此字符串中最后一次出现处的索引。 |
boolean matches(String regex) | 告知此字符串是否匹配给定的正则表达式。 |
String substring(int beginindex) | 返回一个新的字符串,它是此字符串的一个子字符串。 |
String[] split(String regex) | 根据给定正则表达式的匹配拆分此字符串。 |
String replace(char oldChar, char newChar) | 返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。 |
在使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,所以如果需要对字符串进行修改推荐使用 StringBuffer。
StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。
由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。
StringBuffer常用方法
方法 | 说明 |
---|---|
StringBuffer append(String s) | 将指定的字符串追加到此字符序列。 |
StringBuffer reverse() | 将此字符序列用其反转形式取代。 |
delete(int start,int end) | 移除此序列的子字符串中的字符。 |
insert(int offset,int i) | 将int 参数的字符串表示形式插入此序列中。 |
replace(int start,int end,String s) | 使用给定 String中的字符替换此序列的子字符串中的字符。 |
Array类
java.util.Arrays 类能方便地操作数组,它提供的所有方法都是静态的。
具有以下功能:
- 给数组赋值:通过 fill 方法。
- 对数组排序:通过 sort 方法,按升序。
- 比较数组:通过 equals 方法比较数组中元素值是否相等。
- 查找数组元素:通过 binarySearch 方法能对排序好的数组进行二分查找法操作。
4、java日期和时间
java.util 包提供了 Date 类来封装当前的日期和时间。
常用方法:
方法 | 说明 |
---|---|
boolean after(Date date) | 若当调用此方法的Date对象在指定日期之后返回true,否则返回false |
boolean before(Date date) | 若当调用此方法的Date对象在指定日期之前返回true,否则返回false |
int compareTo(Data date) | 比较当调用此方法的Date对象和指定日期。两者相等时候返回0。调用对象在指定日期之前则返回负数。调用对象在指定日期之后则返回正数 |
int compareTo(Object o) | 若obj是Date类型则操作等同于compareTo(Date) 。否则它抛出ClassCastException |
boolean equals(Object date) | 当调用此方法的Date对象和指定日期相等时候返回true,否则返回false。 |
long getTime() | 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数 |
void setTime(long time) | 用自1970年1月1日00:00:00 GMT以后time毫秒数设置时间和日期。 |
String toString() | 把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat)。 |
SimpleDateFormat 类有一些附加的方法,特别是parse(),它试图按照给定的SimpleDateFormat 对象的格式化存储来解析字符串。
设置和获取日期数据的特定部分使用Calendar类。
5、java正则表达式
java.util.regex 包主要包括以下三个类:
-
Pattern 类:
pattern 对象是一个正则表达式的编译表示。Pattern类的作用在于编译正则表达式后创建一个匹配模式。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
-
Matcher 类:
Matcher类使用Pattern实例提供的模式信息对正则表达式进行匹配。
Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
-
PatternSyntaxException:
PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。
Pattern类常用方法:
方法 | 说明 |
---|---|
Pattern.complie(String regex) | 由于Pattern的构造函数是私有的,不可以直接创建,所以通过静态方法compile(String regex)方法来创建,将给定的正则表达式编译并赋予给Pattern类 |
Pattern.split(CharSequence arg0) | 用于分隔字符串,并返回一个String[] |
Pattern.matcher(String regex,CharSequence input) | 该方法是个静态方法,用于快速匹配字符串,该方法适合用于只匹配一次,且匹配全部字符串,不会生成Matcher对象 |
Pattern.matcher(CharSequence input) | 对指定输入的字符串创建一个Matcher对象 |
Matcher类常用方法:
方法 | 说明 |
---|---|
boolean matches() | 尝试对整个目标字符展开匹配检测,也就是只有整个目标字符串完全匹配时才返回真值 |
boolean lookingAt() | 对前面的字符串进行匹配,只有匹配到的字符串在最前面才会返回true |
boolean find() | 对字符串进行匹配,匹配到的字符串可以在任何位置 |
int start() | 返回当前匹配到的字符串在原目标字符串中的位置 |
int end() | 返回当前匹配的字符串的最后一个字符在原目标字符串中的索引位置 |
String group() | 返回匹配到的子字符串 |
只有当匹配操作成功(成功就是当matches(),lookingAt(),find()其中任意一个方法返回true时),才可以使用start(),end(),group()三个方法。
6、finalize() 方法
Java 允许定义这样的方法,它在对象被垃圾收集器析构(回收)之前调用,这个方法叫做 finalize( ),它用来清除回收对象。
例如,你可以使用 finalize() 来确保一个对象打开的文件被关闭了。
在 finalize() 方法里,你必须指定在对象销毁时候要执行的操作。
finalize() 一般格式是:
protected void finalize()
{
// 在这里终结代码
}
7、Scanner类
可以通过 Scanner 类来获取用户的输入。
下面是创建 Scanner 对象的基本语法:
Scanner s = new Scanner(System.in);
通过 Scanner 类的 next() 与 nextLine() 方法获取输入的字符串,在读取前我们一般需要 使用 hasNext 与 hasNextLine 判断是否还有输入的数据。
Scanner scan = new Scanner(System.in);
System.out.println("nextline方式接收:");
//判断是否还有输入
if (scan.hasNextLine()){
String str1 = scan.nextLine();
System.out.println("输入的数据为:"+str1);
}
scan.close();
next() 与 nextLine() 区别
next():
- 1、一定要读取到有效字符后才可以结束输入。
- 2、对输入有效字符之前遇到的空白,next() 方法会自动将其去掉。
- 3、只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。
- next() 不能得到带有空格的字符串。
nextLine():
- 1、以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。
- 2、可以获得空白。
如果要输入 int 或 float 类型的数据,在 Scanner 类中也有支持,但是在输入之前最好先使用 hasNextXxx() 方法进行验证,再使用 nextXxx() 来读取
8、throw和throws
抛出异常有三种形式
-
throw
-
throws
-
系统自动抛异常
throws出现在方法函数头;而throw出现在函数体。
throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常对象。
两者都是消极处理异常的方式(这里的消极并不是说这种方式不好),只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。 -
在写程序时,对可能会出现异常的部分通常要用try{…}catch{…}去捕捉它并对它进行处理;
-
用try{…}catch{…}捕捉了异常之后一定要对在catch{…}中对其进行处理,那怕是最简单的一句输出语句,或栈输入e.printStackTrace();用try{…}catch{…}捕捉了异常之后一定要对在catch{…}中对其进行处理,那怕是最简单的一句输出语句,或栈输入e.printStackTrace();
-
如果是捕捉IO输入输出流中的异常,一定要在try{…}catch{…}后加finally{…}把输入输出流关闭;如果是捕捉IO输入输出流中的异常,一定要在try{…}catch{…}后加finally{…}把输入输出流关闭;
-
如果在函数体内用throw抛出了某种异常,最好要在函数名中加throws抛异常声明,然后交给调用它的上层函数进行处理。如果在函数体内用throw抛出了某种异常,最好要在函数名中加throws抛异常声明,然后交给调用它的上层函数进行处理。
9、继承的特性
- 子类拥有父类非 private 的属性、方法。
- 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
- 子类可以用自己的方式实现父类的方法。
- Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
- 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。
super 与 this 关键字
super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
this关键字:指向自己的引用。
final关键字
final 关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写。
子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。
如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。
重写与重载
重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!
重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。
重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
最常用的地方就是构造器的重载。
重载规则:
-
被重载的方法必须改变参数列表(参数个数或类型不一样);
-
被重载的方法可以改变返回类型;
-
被重载的方法可以改变访问修饰符;
-
被重载的方法可以声明新的或更广的检查异常;
-
方法能够在同一个类中或者在一个子类中被重载。
-
无法以返回值类型作为重载函数的区分标准。
重写规则:
-
参数列表与被重写方法的参数列表必须完全相同。
-
返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)。
-
访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。
-
父类的成员方法只能被它的子类重写。
-
声明为 final 的方法不能被重写。
-
声明为 static 的方法不能被重写,但是能够被再次声明。
-
子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
-
子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。
-
重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
-
构造方法不能被重写。
-
如果不能继承一个类,则不能重写该类的方法。
10、抽象类与抽象方法
- 抽象类不能被实例化,如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
- 抽象类中不一定包含抽象方法,也可以有普通的方法,但是有抽象方法的类必定是抽象类。
- 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
- 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
- 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
抽象类存在的意义: 抽象类可以将设计和实现分离 , 抽象类往往用来表征对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。 抽象类不能被实例化,用的时候,根据需要的子类来实例化,这就是抽象类被抽象出来的意义。
11、java接口
接口与类相似点:
- 一个接口可以有多个方法。
- 接口文件保存在 .java 结尾的文件中,文件名使用接口名。
- 接口的字节码文件保存在 .class 结尾的文件中。
- 接口相应的字节码文件必须在与包名称相匹配的目录结构中。
接口与类的区别:
- 接口不能用于实例化对象。
- 接口没有构造方法。
- 接口中所有的方法必须是抽象方法。
- 接口不能包含成员变量,除了 static 和 final 变量。
- 接口不是被类继承了,而是要被类实现。
- 接口支持多继承。
接口特性
-
接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。接口中的方法都是公有的。
-
接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。
-
接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。
-
接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键字。
抽象类和接口的区别
- 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
- 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
- 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
- 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
注:JDK1.8之后,接口里可以有静态方法和方法体了。
[可见度] interface 接口名称 [extends 其他的接口名] {
// 声明变量
// 抽象方法
}
12、Java枚举enum类
java 枚举类使用 enum 关键字来定义,各个常量使用逗号 , 来分割。
例如定义一个颜色的枚举类。
enum Color
{
RED, GREEN, BLUE;
}
enum 定义的枚举类默认继承了 java.lang.Enum 类,并实现了 java.lang.Seriablizable 和 java.lang.Comparable 两个接口。
values(), ordinal() 和 valueOf() 方法位于 java.lang.Enum 类中:
- values() 返回枚举类中所有的值。
- ordinal()方法可以找到每个枚举常量的索引,就像数组索引一样。
- valueOf()方法返回指定字符串值的枚举常量。
13、Java数据结构
Java集合类存放于java.util包中,是一个用来存放对象的容器。
Java集合可以分为Set、List和Map三大种体系。
Set:无序、不可重复的集合;
List:有序,可重复的集合;
Map:具有映射关系的集合;
HashSet
HashSet是Set接口的典型实现,按Hash算法来存储集合中的元素。存入数据时,会调用该对象的hashCode()方法来得到该对象的hashcode值,然后在根据该值决定该对象在HashSet中的存储位置。
特点:
#不能保证元素的排列顺序;
#不可重复;
#HashSet不是线程安全的;
#集合元素可以使用null;
#一些方法
Set set= new HashSet();
set.add('a');//添加元素
set.add(null)
set.contains('a');//判断是否包含元素
set.remove('a');//移除元素
set.size();//获取集合的元素个数
set.clear();//清空集合
//可以使用Iterator迭代器遍历,还可以通过for each遍历
for(Object obj:set){
//...
}
TreeSet
TreeSet是SortSet接口的实现类,TreeSet可以确保集合元素处于排序状态。
TreeSet支持两种排序方法:自然排序和定制排序,默认使用自然排序。
TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之间的大小关系,然后将集合元素按升序排列。
定制排序:在创建TreeSet集合对象时,提供一个实现Comparator接口的类对象,重写compare()方法,由该对象负责集合元素的排序逻辑。
List与ArrayList
List代表一个元素有序、可重复的集合,集合中的每个元素都有其对应的顺序索引,默认按元素的添加顺序设置元素的索引,可以使用索引来访问指定位置的集合元素。
List是接口,ArrayList实现List接口,List list = new ArrayList();
Map接口与HashMap类
Map用于保存具有映射关系的数据,Map集合中保存着键值对,Key和value都可以是任何引用类型的数据。Map中的key是不允许重复的,通过指定的key总能找到唯一的确定的value。
Map<String,Integer> map = new HashMap<String,Integer>();
//保存数据
map.put("a",1);
map.put("b",2);
map.put("c",3);
map.put("d",5);
map.put("e",6);
//根据key取值,return value
map.get("a");
//根据key移除键值对
map.remove("a");
//map集合的长度,return int
map.size();
//判断当前的map集合是否包含指定的key
map.containsKey("b");
//判断当前的map集合是否包含指定的value
map.containsValue(2);
//获取map集合的所有key的集合
Set<String> keys =map.keySet();
//获取map集合的所有value的集合
map.values();
//遍历map集合
for (String key:keys) {
System.out.println("key:"+key+"\tvalue:"+map.get(key));
}
//遍历map集合
Set<Map.Entry<String,Integer>> entrys =map.entrySet();
for (Map.Entry<String,Integer> en: entrys) {
System.out.println("en.key:"+en.getKey()+"\ten.value:"+en.getValue());
}
//清空集合
map.clear();
/**
*输出
* key:b value:2
* key:c value:3
* key:d value:5
* key:e value:6
* en.key:b en.value:2
* en.key:c en.value:3
* en.key:d en.value:5
* en.key:e en.value:6
*/
HashMap和HashTable
都是Map接口的典型实现类;
HashTable是线程安全的Map实现,HashMap是线程不安全的;
HashTable不允许使用null作为key和value,而HashMap可以;
Collections操作集合的工具类
Collections是一个操作Set、List和Map等集合的工具类;
Collections中提供了大量方法对集合元素进行排序、查询和修改等操作,还提供对集合对象设置不可变、对集合对象实现同步控制等方法。
//反转List中元素的顺序
Collections.reverse(List);
//对List中元素进行随机排序
Collections.shuffle(List);
//根据元素的自然顺序对指定List集合元素进行升序排序
Collections.sort(List);
//根据指定的Comparator产生的顺序对List集合元素进行排序
Collections.sort(List,Comparator);
//将指定List集合中的i处元素与j处元素进行交换
Collections.swap(List,int,int)
Object Collections.max(Collection);
Object Collections.min(Collection);
//返回指定集合中元素的出现次数
Collections.frequency(Collection,Object);
//使用新值替换List对象的所有旧值
Collections.replaceall(List list,Object oldvalue,Object newvalue);
注意:Collections类中提供了synchronizedXxx()方法,可使指定集合包装成线程同步的集合,可以解决多线程并发访问集合时的线程安全问题。
泛型
Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
Java中的泛型,只在编译阶段有效。
14、java实现单例模式
饿汉式单例模式
懒汉式单例模式
以上情况还是会出现单例对象不唯一的现象,需要进行双重检查锁定。
补充
instanceof运算符
对象A是不是类B或其子类的实例对象;
A instanceof B :return True/False
==和equals()
基本数据类型:
- ==比较值,两个变量的值相等即为true;
引用数据类型:
- ==比较引用,是否指向同一对象,指向同一对象即为True,比较对象的地址;
- equals()只能比较引用对象,比较是否指向同一对象;
- **注意:**当File、String、Date以及包装类使用equals()进行比较时,是比较类型及内容而不是考虑引用的是否是同一个对象。(这些类重写了Object类的equals()方法。)
java内部类可以间接解决类不能多重继承的问题。