[Java] Java Basic : preview

基础教学:lecturevideolecturer: Matt Stokerhtml

Java教学:http://www.runoob.com/java/java-intro.html【菜鸟教程,很是适合复习】java

Ref: JAVA 学到什么水平就能够转战 Android 了mysql

 

Ref:设计模式菜鸟教程android

Ref:Java教程git

Ref: Java code 实例程序员

 

复习感觉:Java已经再也不是过去熟悉的Java!github

 

 第一课:web

 

 

观后感,应该总结一套控件代码:控件代码收集面试

看上去不错de样子。后记,貌似没有用了,有了Material Design。正则表达式

 

Ref: chenyangcun/MaterialDesignExample

Ref: 加载图片助手:https://www.fresco-cn.org/

 

第二课:

现代Android开发:一些建议

若是是 色彩盲,请自行收藏这个网站Material Design Color Palette Generator 【颜色、图标】
从一开始起就严格按照material design写Material Design

不要自定义一堆padding margin,但你须要边框,边距的时候,请看看 ?android:attr/里面有木有你需求的(因为android studio强大的补全功能,你通常只需打几个关键词就有提示了),好比你须要给一个ImageButton加点击效果, 不要傻不拉几的去写一个selector了,你只须要输入 item select这些关键词,自动补全就会给你提示了。

不要定义一大堆乱七八糟的 字体大小了,materail design上的几种基本字体大小能够知足你!

再也 不要使用ListView了,改为RecycleView

再也 不要寻找第三方下拉刷新控件了,SwipeRefreshLayout确定符合你的要求(不信你看,知乎Android客户端都是用的这个(●ˇ∀ˇ●))。

再也 不要使用第三方侧滑栏了,DrawerLayout能知足你!

再也 不要使用ViewPagerTabStripe这一类的第三方Tab控件了,请使用TabLayout!

再也 不用找圆形头像控件,圆角控件了,其余的Univeral Image Loader /Picasso也不用看了,直接上Fresco | Fresco 中文说明吧,它都有!不如用省下的时间看看Fresco的源码。
 

关于Material Design,控件章节作介绍。

相关视频讲解:谷歌Material Design设计语言详解

 

 

 

这里先复习下Java语言基础知识,耗时五小时。 

参考:Java 教程

 

初步复习内容

 

Java分为三个体系:

  • JavaSE (J2SE)  (Java2 Platform Standard Edition,java平台标准版)
  • JavaEE (J2EE)  (Java 2 Platform,Enterprise Edition,java平台企业版)
  • JavaME (J2ME)  (Java 2 Platform Micro Edition,java平台微型版)。

   

基本语法

  • 主方法入口:全部的Java 程序由public static void main(String []args)方法开始执行。

Java标识符

  • 全部的标识符都应该以字母(A-Z或者a-z),美圆符($)、或者下划线(_)开始
  • 首字符以后能够是字母(A-Z或者a-z),美圆符($)、下划线(_)或数字的任何字符组合

Java修饰符

像其余语言同样,Java可使用修饰符来修饰类中方法和属性。主要有两类修饰符:

  • 访问控制修饰符 : default, public , protected, private
  • 非访问控制修饰符 : final, abstract, strictfp

Java变量

Java中主要有以下几种类型的变量

  • 局部变量
  • 类变量(静态变量)
  • 成员变量(非静态变量)

Java数组


Java枚举


Java关键字

下面列出了Java保留字。这些保留字不能用于常量、变量、和任何标识符的名称。

类别 关键字 说明
访问控制 private 私有的
protected 受保护的
public 公共的
类、方法和变量修饰符 abstract 声明抽象
class
extends 扩允,继承
final 最终值,不可改变的
implements 实现(接口)
interface 接口
native 本地,原生方法(非Java实现)
new 新,建立
static 静态
strictfp 严格,精准
synchronized 线程,同步
transient 短暂
volatile 易失
程序控制语句 break 跳出循环
case 定义一个值以供switch选择
continue 继续
default 默认
do 运行
else 不然
for 循环
if 若是
instanceof 实例
return 返回
switch 根据值选择执行
while 循环
错误处理 assert 断言表达式是否为真
catch 捕捉异常
finally 有没有异常都执行
throw 抛出一个异常对象
throws 声明一个异常可能被抛出
try 捕获异常
包相关 import 引入
package
基本类型 boolean 布尔型
byte 字节型
char 字符型
double 双精度浮点
float 单精度浮点
int 整型
long 长整型
short 短整型
null
变量引用 super 父类,超类
this 本类
void 无返回值
保留关键字 goto 是关键字,但不能使用
const 是关键字,但不能使用

 


Java注释


Java 空行


继承

被继承的类称为超类(super class),派生类称为子类(subclass)。


接口


 

 

详细的复习内容

 

Java 对象和类

public class Puppy{
int puppyAge;
static int cls_var = 10
public Puppy(String name){ System.out.println("小狗的名字是 : " + name ); } public void setAge( int age ){ puppyAge = age; } public int getAge( ){ System.out.println("小狗的年龄为 : " + puppyAge ); return puppyAge; } public static void main(String []args){ Puppy myPuppy = new Puppy( "tommy" ); myPuppy.setAge( 2 ); myPuppy.getAge( );   System.out.println("变量值 : " + myPuppy.puppyAge ); } }

 

源文件声明规则

    • 一个源文件中只能有一个public类
    • 一个源文件能够有多个非public类
    • 顺序:package语句、import语句、类定义。
    • import语句和package语句对源文件中定义的全部类都有效。在同一源文件中,不能给不一样的类不一样的包声明。

Ref: Java安装相关路径查找

 

Java 基本数据类型

  • 内置数据类型

byte,节省空间。

System.out.println("基本类型:byte 二进制位数:" + Byte.SIZE);
System.out.println("包装类:java.  .Byte");
System.out.println("最小值:Byte.MIN_VALUE=" + Byte.MIN_VALUE);
System.out.println("最大值:Byte.MAX_VALUE=" + Byte.MAX_VALUE);
  • 引用类型

对象、数组都是引用数据类型。

全部引用类型的默认值都是null。

  • Java 常量
final double PI = 3.1415927;
  • 自动类型转换
低  ------------------------------------>byte,short,char—> int —> long—> float —> double 
  • 强制类型转换
  • 隐含强制类型转换

Ref: 例子不错的连接

 

Java 变量类型

Java 修饰符

  • 访问修饰符

咱们能够经过如下表来讲明访问权限:

修饰符 当前类 同一包内 子孙类 其余包
public Y Y Y Y
protected Y Y Y N
default Y Y N N
private Y N N N

 

 

 

 

 

  • 非访问修饰符

static变量

static方法

final变量,

final方法,不能被子类修改

final类,不能被继承其任何特性

abstract方法

abstract类,包含若干个抽象方法则必为抽象类,或抽象类能够不包含抽象方法

 

synchronized 修饰符

public synchronized void showDetails(){
.......
}

 

transient 修饰符

对应的变量加上transient关键字,那么,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。

参考:http://www.javashuo.com/article/p-odbasryu-n.html

 

volatile 修饰符

Java语言规范中指出:为了得到最佳速度,容许线程保存共享成员变量的私有拷贝,并且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。

这样当多个线程同时与某个对象交互时,就必需要注意到要让线程及时的获得共享成员变量的变化。

使用建议:在两个或者更多的线程访问的成员变量上使用volatile。当要访问的变量已在synchronized代码块中,或者为常量时,没必要使用。

因为使用volatile屏蔽掉了VM中必要的代码优化,因此在效率上比较低,所以必定在必要时才使用此关键字。

 

Java 运算符

instanceof 运算符

String name = "James";
boolean result = name instanceof String; // 因为 name 是 String 类型,因此返回真

  

Java 循环结构 - for, while 及 do...while

Java 加强 for 循环,为方便数组访问。

public class Test {
public static void main(String args[]){
int [] numbers = {10, 20, 30, 40, 50}; for(int x : numbers ){ System.out.print( x ); System.out.print(","); }
} }

 

Java 分支结构 - if...else/switch

Java Number & Math 类

  • Number类

全部的包装类(Integer、Long、Byte、Double、Float、Short)都是抽象类 Number 的子类。

当 x 被赋为整型值时,

    • 因为x是一个对象,因此编译器要对x进行装箱
    • 而后,为了使x能进行加运算,因此要对x进行拆箱
Integer x = 5;
x =  x + 10;
  • Math 类
public class Test {  
    public static void main (String []args)  
    {  
        System.out.println("90 度的正弦值:" + Math.sin(Math.PI/2));  
        System.out.println("0度的余弦值:"   + Math.cos(0));  
        System.out.println("60度的正切值:"  + Math.tan(Math.PI/3));  
        System.out.println("1的反正切值: "  + Math.atan(1));  
        System.out.println("π/2的角度值:"  + Math.toDegrees(Math.PI/2));  
        System.out.println(Math.PI);  
    }  
}

 

Java Character 类

提供了一些好用的方法:

1 isLetter()
是不是一个字母
2 isDigit()
是不是一个数字字符
3 isWhitespace()
是不是一个空格
4 isUpperCase()
是不是大写字母
5 isLowerCase()
是不是小写字母
6 toUpperCase()
指定字母的大写形式
7 toLowerCase()
指定字母的小写形式
8 toString()
返回字符的字符串形式,字符串的长度仅为1

 

Java String 类

1    char charAt(int index)
返回指定索引处的 char 值。
2    int compareTo(Object o)
把这个字符串和另外一个对象比较。
3    int compareTo(String anotherString)
按字典顺序比较两个字符串。
4    int compareToIgnoreCase(String str)
按字典顺序比较两个字符串,不考虑大小写。
5    String concat(String str)
将指定字符串链接到此字符串的结尾。
6    boolean contentEquals(StringBuffer sb)
当且仅当字符串与指定的StringButter有相同顺序的字符时候返回真。
7    static String copyValueOf(char[] data)
返回指定数组中表示该字符序列的 String。
8    static String copyValueOf(char[] data, int offset, int count)
返回指定数组中表示该字符序列的 String。
9    boolean endsWith(String suffix)
测试此字符串是否以指定的后缀结束。
10    boolean equals(Object anObject)
将此字符串与指定的对象比较。
11    boolean equalsIgnoreCase(String anotherString)
将此 String 与另外一个 String 比较,不考虑大小写。
12    byte[] getBytes()
使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
13    byte[] getBytes(String charsetName)
使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
14    void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
将字符今后字符串复制到目标字符数组。
15    int hashCode()
返回此字符串的哈希码。
16    int indexOf(int ch)
返回指定字符在此字符串中第一次出现处的索引。
17    int indexOf(int ch, int fromIndex)
返回在此字符串中第一次出现指定字符处的索引,从指定的索引开始搜索。
18    int indexOf(String str)
返回指定子字符串在此字符串中第一次出现处的索引。
19    int indexOf(String str, int fromIndex)
返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。
20    String intern()
返回字符串对象的规范化表示形式。
21    int lastIndexOf(int ch)
返回指定字符在此字符串中最后一次出现处的索引。
22    int lastIndexOf(int ch, int fromIndex)
返回指定字符在此字符串中最后一次出现处的索引,从指定的索引处开始进行反向搜索。
23    int lastIndexOf(String str)
返回指定子字符串在此字符串中最右边出现处的索引。
24    int lastIndexOf(String str, int fromIndex)
返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。
25    int length()
返回此字符串的长度。
26    boolean matches(String regex)
告知此字符串是否匹配给定的正则表达式。
27    boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)
测试两个字符串区域是否相等。
28    boolean regionMatches(int toffset, String other, int ooffset, int len)
测试两个字符串区域是否相等。
29    String replace(char oldChar, char newChar)
返回一个新的字符串,它是经过用 newChar 替换此字符串中出现的全部 oldChar 获得的。
30    String replaceAll(String regex, String replacement
使用给定的 replacement 替换此字符串全部匹配给定的正则表达式的子字符串。
31    String replaceFirst(String regex, String replacement)
使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
32    String[] split(String regex)
根据给定正则表达式的匹配拆分此字符串。
33    String[] split(String regex, int limit)
根据匹配给定的正则表达式来拆分此字符串。
34    boolean startsWith(String prefix)
测试此字符串是否以指定的前缀开始。
35    boolean startsWith(String prefix, int toffset)
测试此字符串从指定索引开始的子字符串是否以指定前缀开始。
36    CharSequence subSequence(int beginIndex, int endIndex)
返回一个新的字符序列,它是此序列的一个子序列。
37    String substring(int beginIndex)
返回一个新的字符串,它是此字符串的一个子字符串。
38    String substring(int beginIndex, int endIndex)
返回一个新字符串,它是此字符串的一个子字符串。
39    char[] toCharArray()
将此字符串转换为一个新的字符数组。
40    String toLowerCase()
使用默认语言环境的规则将此 String 中的全部字符都转换为小写。
41    String toLowerCase(Locale locale)
使用给定 Locale 的规则将此 String 中的全部字符都转换为小写。
42    String toString()
返回此对象自己(它已是一个字符串!)。
43    String toUpperCase()
使用默认语言环境的规则将此 String 中的全部字符都转换为大写。
44    String toUpperCase(Locale locale)
使用给定 Locale 的规则将此 String 中的全部字符都转换为大写。
45    String trim()
返回字符串的副本,忽略前导空白和尾部空白。
46    static String valueOf(primitive data type x)
返回给定data type类型x参数的字符串表示形式。
View Code

 

Java StringBuffer 和 StringBuilder 类

当对字符串进行修改:

    • StringBuilder:更快!
    • StringBuffer:线程安全!

本身特有的方案,其余与String类似。

序号 方法描述
1 public StringBuffer append(String s)
将指定的字符串追加到此字符序列。
2 public StringBuffer reverse()
将此字符序列用其反转形式取代。
3 public delete(int start, int end)
移除此序列的子字符串中的字符。
4 public insert(int offset, int i)
将 int 参数的字符串表示形式插入此序列中。
5 replace(int start, int end, String str)
使用给定 String 中的字符替换此序列的子字符串中的字符。

  

Java 数组

值传递:为何 Java 只有值传递,但 C# 既有值传递,又有引用传递,这种语言设计有哪些好处?

dataType[] arrayRefVar = new dataType[arraySize];
dataType[] arrayRefVar = {value0, value1, ..., valuek};

String str[][] = new String[3][4];

 

Arrays 类 

序号 方法和说明
1 public static int binarySearch(Object[] a, Object key)
用二分查找算法在给定数组中搜索给定值的对象(Byte,Int,double等)。数组在调用前必须排序好的。若是查找值包含在数组中,则返回搜索键的索引;不然返回 (-(插入点) - 1)。
2 public static boolean equals(long[] a, long[] a2)
若是两个指定的 long 型数组彼此相等,则返回 true。若是两个数组包含相同数量的元素,而且两个数组中的全部相应元素对都是相等的,则认为这两个数组是相等的。换句话说,若是两个数组以相同顺序包含相同的元素,则两个数组是相等的。一样的方法适用于全部的其余基本数据类型(Byte,short,Int等)。
3 public static void fill(int[] a, int val)
将指定的 int 值分配给指定 int 型数组指定范围中的每一个元素。一样的方法适用于全部的其余基本数据类型(Byte,short,Int等)。
4 public static void sort(Object[] a)
对指定对象数组根据其元素的天然顺序进行升序排列。一样的方法适用于全部的其余基本数据类型(Byte,short,Int等)。

 

Java 日期时间

Java 正则表达式

参见:[PyProj] Think in Python : Regex

java.util.regex 包主要包括如下三个类:

    • Pattern 类:

      pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要建立一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式做为它的第一个参数。

    • Matcher 类:

      Matcher 对象是对输入字符串进行解释和匹配操做的引擎。与Pattern 类同样,Matcher 也没有公共构造方法。你须要调用 Pattern 对象的 matcher 方法来得到一个 Matcher 对象。

    • PatternSyntaxException:

      PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。

import java.util.regex.*;
 
class RegexExample1{
public static void main(String args[]){
String content
= "I am noob " + "from runoob.com."; String pattern = ".*runoob.*"; boolean isMatch = Pattern.matches(pattern, content);  // <---- System.out.println("字符串中是否包含了 'runoob' 子字符串? " + isMatch); } }

More详见原文

 

Java 方法

  • 可变参数
public class VarargsDemo {
public static void main(String args[]) {
// 调用可变参数的方法 printMax(34, 3, 3, 2, 56.5); printMax(new double[]{1, 2, 3}); } public static void printMax( double... numbers) {  //numbers已经变成了一个数组 if (numbers.length == 0) { System.out.println("No argument passed"); return; } double result = numbers[0]; for (int i = 1; i < numbers.length; i++){ if (numbers[i] > result) { result = numbers[i]; } } System.out.println("The max value is " + result); } }
  • finalize() 方法
public class FinalizationDemo {  
public static void main(String[] args) { Cake c1 = new Cake(1); Cake c2 = new Cake(2); Cake c3 = new Cake(3); c2 = c3 = null; System.gc(); //调用Java垃圾收集器,当垃圾回收器(garbage colector)决定回收某对象时,就会运行该对象的finalize()方法。 } }
class Cake extends Object {   //finalize()是在java.lang.Object里定义的 private int id; public Cake(int id) { this.id = id; System.out.println("Cake Object " + id + "is created"); } protected void finalize() throws java.lang.Throwable { super.finalize(); System.out.println("Cake Object " + id + "is disposed"); } }

Java 容许定义这样的方法,它在对象被垃圾收集器析构(回收)以前调用,这个方法叫作 finalize( ),它用来清除回收对象。

注意:但有一种JNI(Java Native Interface)调用non-Java程序(C或C++),finalize()的工做就是回收这部分的内存。【在自动回收内存垃圾以外的使用状况】

 

Java 流(Stream)、文件(File)和IO 

  • 控制台的流

  • 读写文件

FileInputStream

InputStream input = new FileInputStream("C:/java/hello");

File f = new File("C:/java/hello");
InputStream input = new FileInputStream(f);
序号 方法及描述
1 public void close() throws IOException{}
关闭此文件输入流并释放与此流有关的全部系统资源。抛出IOException异常。
2 protected void finalize() throws IOException {}
这个方法清除与该文件的链接。确保在再也不引用文件输入流时调用其 close 方法。抛出IOException异常。
3 public int read(int r) throws IOException{}
这个方法从 InputStream 对象读取指定字节的数据。返回为整数值。返回下一字节数据,若是已经到结尾则返回-1。
4 public int read(byte[] r) throws IOException{}
这个方法从输入流读取r.length长度的字节。返回读取的字节数。若是是文件结尾则返回-1。
5 public int available() throws IOException{}
返回下一次对此输入流调用的方法能够不受阻塞地今后输入流读取的字节数。返回一个整数值。

其余的输入流

 

FileOutputStream

OutputStream output = new FileOutputStream("C:/java/hello")

File f = new File("C:/java/hello");
OutputStream output = new FileOutputStream(f);
序号 方法及描述
1 public void close() throws IOException{}
关闭此文件输入流并释放与此流有关的全部系统资源。抛出IOException异常。
2 protected void finalize() throws IOException {}
这个方法清除与该文件的链接。确保在再也不引用文件输入流时调用其 close 方法。抛出IOException异常。
3 public void write(int w) throws IOException{}
这个方法把指定的字节写到输出流中。
4 public void write(byte[] w)
把指定数组中w.length长度的字节写到OutputStream中。

 其余的输出流

 

以上是字节流; --> 例子,解决乱码问题

下面是字符流;--> 关于文件和I/O的类

 

import java.io.*;
public class FileRead{ public static void main(String args[])throws IOException{
File file
= new File("Hello1.txt"); // 建立文件 file.createNewFile(); // creates a FileWriter Object FileWriter writer = new FileWriter(file); // 向文件写入内容 writer.write("This\n is\n an\n example\n"); writer.flush(); writer.close();
// 建立 FileReader 对象 FileReader fr = new FileReader(file); char [] a = new char[50]; fr.read(a); // 读取数组中的内容 for(char c : a) System.out.print(c); // 一个一个打印字符 fr.close(); } }

 

Java Scanner 类

  • next 方法

import java.util.Scanner; 
 
public class ScannerDemo {
    public static void main(String[] args) {
Scanner scan
= new Scanner(System.in); // 从键盘接收数据 // next方式接收字符串 System.out.println("next方式接收:"); // 判断是否还有输入 if (scan.hasNext()) { String str1 = scan.next(); System.out.println("输入的数据为:" + str1); } scan.close(); } }
  • next() 与 nextLine() 区别

next():

    • 一、必定要读取到有效字符后才能够结束输入。
    • 二、对输入有效字符以前遇到的空白,next() 方法会自动将其去掉。
    • 三、只有输入有效字符后才将其后面输入的空白做为分隔符或者结束符。
    • next() 不能获得带有空格的字符串。

nextLine():

    • 一、以Enter为结束符,也就是说 nextLine()方法返回的是输入回车以前的全部字符。
    • 二、能够得到空白。

 

Java 异常处理

产品级代码的必会重点,连接这里

例子:

    • 用户输入了非法数据。
    • 要打开的文件不存在。
    • 网络通讯时链接中断,或者JVM内存溢出。

三类:

    • 检查性异常:最具表明的检查性异常是用户错误或问题引发的异常,这是程序员没法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
    • 运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常能够在编译时被忽略
    • 错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中一般被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。

 

Java 内置异常类

  • 在 java.lang 包的非检查性异常类
异常 描述
ArithmeticException 当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例。
ArrayIndexOutOfBoundsException 用非法索引访问数组时抛出的异常。若是索引为负或大于等于数组大小,则该索引为非法索引。
ArrayStoreException 试图将错误类型的对象存储到一个对象数组时抛出的异常。
ClassCastException 当试图将对象强制转换为不是实例的子类时,抛出该异常。
IllegalArgumentException 抛出的异常代表向方法传递了一个不合法或不正确的参数。
IllegalMonitorStateException 抛出的异常代表某一线程已经试图等待对象的监视器,或者试图通知其余正在等待对象的监视器而自己没有指定监视器的线程。
IllegalStateException 在非法或不适当的时间调用方法时产生的信号。换句话说,即 Java 环境或 Java 应用程序没有处于请求操做所要求的适当状态下。
IllegalThreadStateException 线程没有处于请求操做所要求的适当状态时抛出的异常。
IndexOutOfBoundsException 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。
NegativeArraySizeException 若是应用程序试图建立大小为负的数组,则抛出该异常。
NullPointerException 当应用程序试图在须要对象的地方使用 null 时,抛出该异常
NumberFormatException 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。
SecurityException 由安全管理器抛出的异常,指示存在安全侵犯。
StringIndexOutOfBoundsException 此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。
UnsupportedOperationException 当不支持请求的操做时,抛出该异常。
  • 在 java.lang 包中的检查性异常类
异常 描述
ClassNotFoundException 应用程序试图加载类时,找不到相应的类,抛出该异常。
CloneNotSupportedException 当调用 Object 类中的 clone 方法克隆对象,但该对象的类没法实现 Cloneable 接口时,抛出该异常。
IllegalAccessException 拒绝访问一个类的时候,抛出该异常。
InstantiationException 当试图使用 Class 类中的 newInstance 方法建立一个类的实例,而指定的类对象由于是一个接口或是一个抽象类而没法实例化时,抛出该异常。
InterruptedException 一个线程被另外一个线程中断,抛出该异常。
NoSuchFieldException 请求的变量不存在
NoSuchMethodException 请求的方法不存在

 

异常方法

下面的列表是 Throwable 类的主要方法:

序号 方法及说明
1 public String getMessage()
返回关于发生的异常的详细信息。这个消息在Throwable 类的构造函数中初始化了。
2 public Throwable getCause()
返回一个Throwable 对象表明异常缘由。
3 public String toString()
使用getMessage()的结果返回类的串级名字。
4 public void printStackTrace()
打印toString()结果和栈层次到System.err,即错误输出流。
5 public StackTraceElement [] getStackTrace()
返回一个包含堆栈层次的数组。下标为0的元素表明栈顶,最后一个元素表明方法调用堆栈的栈底。
6 public Throwable fillInStackTrace()
用当前的调用栈层次填充Throwable 对象栈层次,添加到栈层次任何先前信息中。

 

try...catch 捕获异常

// 文件名 : ExcepTest.java
import java.io.*;
public class ExcepTest{
 
   public static void main(String args[]){
      try{
int a[] = new int[2]; System.out.println("Access element three :" + a[3]);
}
catch(ArrayIndexOutOfBoundsException e){  // 处理数组越界
System.
out.println("Exception thrown :" + e); }
System.
out.println("Out of the block"); } }

扩展 之 多重捕获。

try {
  file = new FileInputStream(fileName);
  x    = (byte) file.read();
}
catch(IOException i){   i.printStackTrace();   return -1;
}
catch(FileNotFoundException f){   f.printStackTrace();   return -1; }

 

好处:

为避免与正常的代码混在一块儿,很差区分开。

所以,Java、C#等设计了try catch这一种特殊的方式。

try{
  ....
  CreateFile( "C:\abc.txt" );
}catch(AccessException e){
  ....//代码进入这里说明发生【没有权限错误】
}catch(FileExistedException e){
  ....//代码进入这里说明发生【文件已经存在错误】
}catch(TimeoutException e){
  ....//代码进入这里说明发生【超时错误】
}

 

更高的认识:

说处处理异常,咱们固然会想到 try catch finally

在java中咱们会对异常的处理有更高的认识 咱们会学习 throw throws等更好的处理异常。

手动抛出异常可是有时候有些错误在jvm看来不是错误,好比说

int age = 0;  
age = -100;  
System.out.println(age);  

 

因此,咱们须要本身手动引起异常,这就是throw的做用。

int age = 0;  
age = -100;  
if(age<0)  
{  
  Exception e = new Exception();  // ----> 建立异常对象  
  throw e;               // ----> 抛出异常  
}  
System.out.println(age); 

 

异常被抛到这个方法的调用者那里,这个有点像下属处理不了的问题就交到上司手里同样,称为回避异常

可是这使得调用这个方法就有了危险,由于谁也不知道这个方法何时会丢一个什么样的异常给调用者。

因此,在定义方法时,就须要在方法头部分使用throws来声明这个方法可能回避的异常

/**
 * fun()可能会抛出两种异常
 */
void fun()throws IOException,SQLException  
{  
    ...  
}  


try{  
  fun();  
  /**
   * 调用fun()的时候,就知道该如何作准备来处理异常了
   */
}catch(IOException e){
   ...
}catch(SQLException e){  
    ...
}

 

 

throws/throw 关键字:

import java.io.*;
public class className
{
  public void deposit(double amount) throws RemoteException, InsufficientFundsException  // 抛出了多个异常,throwable的子类
  {
    // Method implementation
    throw new RemoteException();
  }
  //Remainder of class definition
}
 

实例:try-catch 和 throw, throws 的区别

public class  ZeroTest {
  public static void main(String[] args) {     try{       int i = 100/ 0;           // 这里遇到算数异常       System.out.print(i);     }catch(Exception e){       System.out.print(1);       throw new RuntimeException();  // 缓存异常后,执行finally     }finally{       System.out.print(2);   // 执行完后,再执行以上缓存中的异常     }
System.out.print(
3);   } }
class A{
    public void func() throws Exception{  // 代表这个方法有可能会抛出一个异常 throw new Exception();
    }
    
    public void g() throws Exception{
        
    }
}

 

声明自定义异常

在 Java 中你能够自定义异常。编写本身的异常类时须要记住下面的几点。

    • 全部异常都必须是 Throwable 的子类。
    • 若是但愿写一个检查性异常类,则须要继承 Exception 类。
    • 若是你想写一个运行时异常类,那么须要继承 RuntimeException 类。

 

简单实例,帮助理解: 

(a). 自定义异常类

// 文件名InsufficientFundsException.java
import java.io.*;
 
//自定义异常类,继承Exception类
public class InsufficientFundsException extends Exception
{
  //此处的amount用来储存当出现异常(取出钱多于余额时)所缺少的钱
  private double amount;
  public InsufficientFundsException(double amount)
  {
    this.amount = amount;
  } 
  public double getAmount()
  {
    return amount;
  }
}

(b). 工具类

// 文件名称 CheckingAccount.java
import java.io.*;
 
//此类模拟银行帐户
public class CheckingAccount
{
  //balance为余额,number为卡号
   private double balance;
   private int number;
   public CheckingAccount(int number)
   {
      this.number = number;
   }
//方法:存钱 public void deposit(double amount) { balance += amount; }
//方法:取钱 public void withdraw(double amount) throws InsufficientFundsException { if(amount <= balance) { balance -= amount; } else { double needs = amount - balance; throw new InsufficientFundsException(needs);  // --> 02.抛出了自定义异常 } }
//方法:返回余额 public double getBalance() { return balance; }
//方法:返回卡号 public int getNumber() { return number; } }

(c). 使用main函数。

//文件名称 BankDemo.java
public class BankDemo
{
   public static void main(String [] args)
   {
      CheckingAccount c = new CheckingAccount(101);
      System.out.println("Depositing $500...");
      c.deposit(500.00);
      try
      {
         System.out.println("\nWithdrawing $100...");
         c.withdraw(100.00);
         System.out.println("\nWithdrawing $600...");
         c.withdraw(600.00);                // --> 01.透支,须要抛出异常
/**
* 上述函数可能会抛出异常,那么下面就作好处理的准备。
* catch是了解withdraw会抛出怎样异常的!
*/ }
catch(InsufficientFundsException e) {       // --> 03. 这里捕获自定义异常
System.out.println(
"Sorry, but you are short $" + e.getAmount()); e.printStackTrace(); } } }

 

 

 

 

 

Java 面向对象


 

Java 继承

  • 全部的类都是继承于 java.lang.Object

单继承:

class 子类 extends 父类 {
  ... }

经过接口多继承:

public interface A {
    public void eat();
    public void sleep();
}
 
public interface B {
    public void show();
}
 
public class C implements A,B {
  ... }

 

  • super 与 this 关键字
class Animal {
  void eat() {
    System.out.println("animal : eat");
  }
}
 
class Dog extends Animal {
  void eat() {     System.out.println("dog : eat");   }
  void eatTest() {     this.eat();   // this 调用本身的方法     super.eat();   // super 调用父类方法   } } public class Test { public static void main(String[] args) { Animal a = new Animal(); a.eat(); Dog d = new Dog(); d.eatTest(); } }

 

  • final关键字

定义为不能继承的,即最终类;

Or 用于修饰方法,该方法不能被子类重写。

final class 类名 {//类体}

  

  • 构造器

构造方法顺序:

class SuperClass {
  private int n;
  SuperClass(){
    System.out.println("SuperClass()");
  }
  SuperClass(int n) {
    System.out.println("SuperClass(int n)");
    this.n = n;
  }
}
class SubClass extends SuperClass{   private int n;   SubClass(){   super(300);  // 给本身的父类传参     System.out.println("SubClass");   }   public SubClass(int n){     System.out.println("SubClass(int n):"+n);     this.n = n;   } }
public class TestSuperSub{   public static void main (String args[]){     SubClass sc = new SubClass();     SubClass sc2 = new SubClass(200);   } }

  

Java 重写(Override)与重载(Overload)

  • Override  【父类与子类的多态性表现】
public class TestDog{
   public static void main(String args[]){
      Animal a = new Animal();     // Animal 对象
      Animal b = new Dog();         // Dog 对象
 
      a.move();            // 执行 Animal 类的方法
      b.move();            //执行 Dog 类的方法
      b.bark();
   }
}

 

  • Overload  【一个类的多态性表现】
区别点 重载方法 重写方法
参数列表 必须修改 必定不能修改
返回类型 能够修改 必定不能修改
异常 能够修改 能够减小或删除,必定不能抛出新的或者更广的异常
访问 能够修改 必定不能作更严格的限制(能够下降限制)

 

Java 多态

多态的实现方式

方式一:重写:

方式二:接口

方式三:抽象类和抽象方法

 

Java 抽象类

From:Java中抽象类和接口的用法和区别

(一)语法层次

    • 在某种程度上来讲,接口是抽象类的特殊化。

(二)设计层次

一、 抽象层次不一样

抽象类:对类抽象;对整个类总体进行抽象,包括属性、行为。

接口 :对行为的抽象;对类局部(行为)进行抽象。

二、 跨域不一样

抽象类:所跨域的是具备类似特色的类,

接口 :能够跨域不一样的类。

三、 设计层次不一样

抽象类:它是自下而上来设计的,咱们要先知道子类才能抽象出父类。

    • 好比咱们只有一个猫类在这里,若是你抽象成一个动物类,是否是设计有点儿过分?咱们起码要有两个动物类,猫、狗在这里,咱们在抽象他们的共同点造成动物抽象类吧!因此说抽象类每每都是经过重构而来的!

接口 :不一样,它根本就不须要知道子类的存在,只须要定义一个规则便可,至于什么子类、何时怎么实现它一律不知。

    • 可是接口就不一样,好比说飞,咱们根本就不知道会有什么东西来实现这个飞接口,怎么实现也不得而知,咱们要作的就是事前定义好飞的行为接口。因此说抽象类是自底向上抽象而来的,接口是自顶向下设计出来的。

 

Java 封装

相似于c#的set, get属性。

/* 文件名: EncapTest.java */
public class EncapTest{
 
   private String name;
   private String idNum;
   private int age;
 
   public int getAge(){
      return age;
   }
 
   public String getName(){
      return name;
   }
 
   public String getIdNum(){
      return idNum;
   }
 
   public void setAge( int newAge){
      age = newAge;
   }
 
   public void setName(String newName){
      name = newName;
   }
 
   public void setIdNum( String newId){
      idNum = newId;
   }
}

/* F文件名 : RunEncap.java */
public class RunEncap{
   public static void main(String args[]){
      EncapTest encap = new EncapTest();
      encap.setName("James");
      encap.setAge(20);
      encap.setIdNum("12343ms");
 
      System.out.print("Name : " + encap.getName() + Age : " + encap.getAge());
    }
}

 

Java 接口

接口的继承

一个接口能继承另外一个接口,和类之间的继承方式比较类似。接口的继承使用extends关键字,子接口继承父接口的方法。

下面的Sports接口被Hockey和Football接口继承:

// 文件名: Sports.java
public interface Sports
{
   public void setHomeTeam(String name);
   public void setVisitingTeam(String name);
}
 
// 文件名: Football.java
public interface Football extends Sports
{
   public void homeTeamScored(int points);
   public void visitingTeamScored(int points);
   public void endOfQuarter(int quarter);
}
 
// 文件名: Hockey.java
public interface Hockey extends Sports    // Hockey接口本身声明了四个方法,从Sports接口继承了两个方法
{
   public void homeGoalScored();
   public void visitingGoalScored();
   public void endOfPeriod(int period);
   public void overtimePeriod(int ot);
}

 

标记接口 

Ref: 第37条:用标记接口定义类型

Ref: 为何这些java接口没有抽象方法?浅谈Java标记接口

好处一:这样针对于不一样的List采起不一样的遍历形式,可让遍历的速度更快。

例如:RandomAccess 

import java.util.List;
import java.util.RandomAccess;

public class SourceLearning
{
    public void iteratorElements(List<String> list)  // 这里的list可能只是override
    {
        if (list instanceof RandomAccess)
        {
            for (int i = 0, size = list.size(); i < size; i++)
            {
                String element = list.get(i);
            }
        }
        else
        {
            for (String element : list)
            {
        // ... ... } } } }

判断是否实现RandomAccess接口,就能够决定采起哪一种遍历的方式。

public class ArrayList<E> extends AbstractList<E>
                          implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
  //...
}
// 而LinkedList就没有实现该标记接口
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable {   //... }

 

好处二:优雅地表示对象是否具有这个能力

例如:Cloneable

标记该对象的是否拥有克隆的能力。

public interface Cloneable {
    ... ...      
}

 

例如:java.io.Serializable

/**
     * Write the specified object to the ObjectOutputStream.  The class of the
     * object, the signature of the class, and the values of the non-transient
     * and non-static fields of the class and all of its supertypes are
     * written.  Default serialization for a class can be overridden using the
     * writeObject and the readObject methods.  Objects referenced by this
     * object are written transitively so that a complete equivalent graph of
     * objects can be reconstructed by an ObjectInputStream.
     *
     * <p>Exceptions are thrown for problems with the OutputStream and for
     * classes that should not be serialized.  All exceptions are fatal to the
     * OutputStream, which is left in an indeterminate state, and it is up to
     * the caller to ignore or recover the stream state.
     *
     * @throws  InvalidClassException Something is wrong with a class used by
     *          serialization.
     * @throws  NotSerializableException Some object to be serialized does not
     *          implement the java.io.Serializable interface.
     * @throws  IOException Any exception thrown by the underlying
     *          OutputStream.
     */
    public final void writeObject(Object obj) throws IOException {
        if (enableOverride) {
            writeObjectOverride(obj);
            return;
        }
        try {
            writeObject0(obj, false);
        } catch (IOException ex) {
            if (depth == 0) {
                writeFatalException(ex);
            }
            throw ex;
        }
    }
View Code

 

Java 包(package)

  • 建立包

在一个.java文件中能够一个public类和多个非public类,若是要将这些类组织在一个包当中,则在.java文件中除注释之外的第一行使用关键字package便可实现。

1 为了尽可能使包名保持惟一性,包名一般采用小写、按倒写互联网址的形式进行定义。如:com.hank.www表示包文件放置的文件路径为com/hank/www。 
2 在进行命名包时,应该避免使用与系统发生冲突的名字,如java.lang、java.swing等。

 

建立了一个叫作animals的包

/* 文件名: Animal.java */
package animals; interface Animal {    // 在包中加入接口 public void eat();
   public void travel();
}

MammalInt.java 文件代码:在同一个包中加入该接口的实现。

package animals; /* 文件名 : MammalInt.java */
public class MammalInt implements Animal{
 
   public void eat(){
      System.out.println("Mammal eats");
   }
 
   public void travel(){
      System.out.println("Mammal travels");
   } 
 
   public int noOfLegs(){
      return 0;
   }
 
   public static void main(String args[]){
      MammalInt m = new MammalInt();
      m.eat();
      m.travel();
   }
}

放在文件夹animals里,而后命令运行:

$ java animals/MammalInt
Mammal eats
Mammal travel

  

  • import 关键字

Boss.java 文件代码:

package payroll;
 
public class Boss
{
   public void payEmployee(Employee e)   //payroll 包已经包含了 Employee 类,不用实用功能全名:payroll.Employee
   {
      e.mailCheck();
   }
}

 

他们两个是互逆过程

package freedom.bean;

将你这个类放在了/freedom/bean/这个文件夹下面,要使用的话

import freedom.bean.*;导入这个类

 

  • 包的使用和设置

一般,一个公司使用它互联网域名的颠倒形式来做为它的包名

例如:互联网域名是 runoob.com,全部的包名都以 com.runoob 开头。包名中的每个部分对应一个子目录。

(1). 该目录下常见文件Runoob.java

....\com\runoob\test\Runoob.java
// 文件名: Runoob.java
package com.runoob.test;
public class Runoob { }
class Google { }

(2). 编译

$javac -d . Runoob.java

获得.class文件

.\com\runoob\test\Runoob.class
.\com\runoob\test\Google.class

放置其它位置,但包名要保持一致!

<path-one>\sources\com\runoob\test\Runoob.java
<path-two>\classes\com\runoob\test\Google.class
|-- class path ---|--- package ---|

这样,你能够将你的类目录分享给其余的编程人员,而不用透露本身的源码。

(3). 设置 CLASSPATH 系统变量

一个 class path 可能会包含好几个路径,多路径应该用分隔符分开。

默认状况下,编译器和 JVM 查找当前目录。

JAR 文件按包含 Java 平台相关的类,因此他们的目录默认放在了 class path 中。

用下面的命令显示当前的CLASSPATH变量:

Windows 平台(DOS 命令行下):C:\> set CLASSPATH
UNIX 平台(Bourne shell 下):# echo $CLASSPATH
删除当前CLASSPATH变量内容:
Windows 平台(DOS 命令行下):C:\> set CLASSPATH=
UNIX 平台(Bourne shell 下):# unset CLASSPATH; export CLASSPATH
设置CLASSPATH变量:

Windows 平台(DOS 命令行下): C:\> set CLASSPATH=C:\users\jack\java\classes
UNIX 平台(Bourne shell 下):# CLASSPATH=/home/jack/java/classes; export CLASSPATH
View Code

 

 

 

Java 高级教程


 

Java 数据结构

  • Enumeration

import java.util.Vector;
import java.util.Enumeration;
 
public class EnumerationTester {
 
   public static void main(String args[]) {
      Enumeration<String> days;
      Vector<String> dayNames = new Vector<String>();
dayNames.add(
"Sunday"); dayNames.add("Monday"); dayNames.add("Tuesday"); dayNames.add("Wednesday"); dayNames.add("Thursday"); dayNames.add("Friday"); dayNames.add("Saturday");
days
= dayNames.elements(); while (days.hasMoreElements()){ System.out.println(days.nextElement()); } } }

 

  • BitSet

理解:bits2.and(bits1); bits2与bits1作运算,bits2发生变化。

import java.util.BitSet;
 
public class BitSetDemo {
 
  public static void main(String args[]) {
     BitSet bits1 = new BitSet(16);
     BitSet bits2 = new BitSet(16);
      
     // set some bits
     for(int i=0; i<16; i++) {
        if((i%2) == 0) bits1.set(i);
        if((i%5) != 0) bits2.set(i);
     }
System.out.println(
"Initial pattern in bits1: "); System.out.println(bits1); System.out.println("\nInitial pattern in bits2: "); System.out.println(bits2); // AND bits bits2.and(bits1); System.out.println("\nbits2 AND bits1: "); System.out.println(bits2); // OR bits bits2.or(bits1); System.out.println("\nbits2 OR bits1: "); System.out.println(bits2); // XOR bits bits2.xor(bits1); System.out.println("\nbits2 XOR bits1: "); System.out.println(bits2); } }

 

  • Vector

能根据须要动态的变化,和ArrayList和类似,区别是什么?

Ref: Arraylist与Vector的区别

  1. 白色的部分是须要去了解的,
  2. 黄色部分是咱们要去重点了解的,不但要知道怎么去用,至少还须要读一次源码。
  3. 绿色部份内容已经不多用了,但在面试题中有可能会问到

 

Vector vs ArrayList

标准答案:

一、Vector是线程安全的,ArrayList不是线程安全的。
二、ArrayList在底层数组不够用时在原来的基础上扩展0.5倍,Vector是扩展1倍。

因此:

无一例外,只要是关键性的操做,方法前面都加了synchronized关键字,来保证线程的安全性。

  1. 单线程的环境中,Vector效率要差不少。
  2. 多线程环境不容许用ArrayList,须要作处理。

 

ArrayList vs LinkedList

  1. ArrayList能够直接经过数组下标获得元素;
  2. LinkedList则须要根据所给的下标从头部或尾部开始往下标的位置依次得到下一个元素或上一个元素。

 

  • Stack
import java.util.*;
 
public class StackDemo {
 
    static void showpush(Stack<Integer> st, int a) {
        st.push(new Integer(a));
        System.out.println("push(" + a + ")");
        System.out.println("stack: " + st);
    }
 
    static void showpop(Stack<Integer> st) {
        System.out.print("pop -> ");
        Integer a = (Integer) st.pop();
        System.out.println(a);
        System.out.println("stack: " + st);
    }
 
    public static void main(String args[]) {
        Stack<Integer> st = new Stack<Integer>();
        System.out.println("stack: " + st);
showpush(st,
42);  // push showpush(st, 66); showpush(st, 99); showpop(st);     // pop showpop(st); showpop(st);
try { showpop(st); } catch (EmptyStackException e) { System.out.println("empty stack"); } } }

 

  • Dictionary/Map

 Dictionary类已通过时了。在实际开发中,你能够实现Map接口来获取键/值的存储功能。

import java.util.*;

public class CollectionsDemo {

   public static void main(String[] args) {
Map m1
= new HashMap(); m1.put("Zara", "8"); m1.put("Mahnaz", "31"); m1.put("Ayan", "12"); m1.put("Daisy", "14");
System.out.println(); System.out.println(
" Map Elements"); System.out.print("\t" + m1); } }

 

  • Java Hashtable/Hashmap 类

hashmap

线程不安全

容许有null的键和值

效率高一点、

方法不是Synchronize的要提供外同步

有containsvalue和containsKey方法

HashMap 是Java1.2 引进的Map interface 的一个实现

HashMap是Hashtable的轻量级实现

hashtable

线程安全

不容许有null的键和值

效率稍低、

方法是是Synchronize的

有contains方法方法

Hashtable 继承于Dictionary 类

Hashtable 比HashMap 要旧

 
 
  • Properties

Ref: Java中Properties类的操做

在Java中,其配置文件常为.properties文件,格式为文本文件,文件的内容的格式是“键=值”的格式,文本注释信息能够用"#"来注释。

它提供了几个主要的方法:

1. getProperty ( String key),用指定的键在此属性列表中搜索属性。也就是经过参数 key ,获得 key 所对应的 value。

2. load ( InputStream inStream),从输入流中读取属性列表(键和元素对)。经过对指定的文件(好比说上面的 test.properties 文件)进行装载来获取该文件中的全部键 - 值对。以供 getProperty ( String key) 来搜索。

3. setProperty ( String key, String value) ,调用 Hashtable 的方法 put 。他经过调用基类的put方法来设置 键 - 值对。

4. store ( OutputStream out, String comments),以适合使用 load 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。与 load 方法相反,该方法将键 - 值对写入到指定的文件中去。

5. clear (),清除全部装载的 键 - 值对。该方法在基类中提供。

 

 

Java 集合框架

Java 集合框架提供了一套性能优良,使用方便的接口和类,java集合框架位于java.util包中, 因此当使用集合框架的时候须要进行导包。

Ref:Java中的集合框架

更详细的图,参考:java集合框架综述

 

Java 泛型

泛型的本质是参数化类型,也就是说所操做的数据类型被指定为一个参数。

假定咱们有这样一个需求:写一个排序方法,可以对整型数组、字符串数组甚至其余任何类型的数组进行排序,该如何实现?

答案:可使用 Java 泛型。

 

  • 泛型方法
public class GenericMethodTest
{
   // 泛型方法 printArray                         
   public static <E> void printArray( E[] inputArray )
   {
      // 输出数组元素            
         for ( E element : inputArray ){        
            System.out.printf( "%s ", element );
         }
         System.out.println();
    }
 
    public static void main( String args[] )
    {
        // 建立不一样类型数组: Integer, Double 和 Character
        Integer[]   intArray    = { 1, 2, 3, 4, 5 };
        Double[]    doubleArray = { 1.1, 2.2, 3.3, 4.4 };
        Character[] charArray   = { 'H', 'E', 'L', 'L', 'O' };
 
        System.out.println( "整型数组元素为:" );
        printArray( intArray  );   // 传递一个整型数组
 
        System.out.println( "\n双精度型数组元素为:" );
        printArray( doubleArray ); // 传递一个双精度型数组
 
        System.out.println( "\n字符型数组元素为:" );
        printArray( charArray );   // 传递一个字符型数组
    } 
}

作一点限制,必须得是可比较的对象:

public class MaximumTest
{
   // 比较三个值并返回最大值
   public static <T extends Comparable<T>> T maximum(T x, T y, T z)
   {                     
      T max = x;
      if ( y.compareTo( max ) > 0 ){
         max = y; 
      }
      if ( z.compareTo( max ) > 0 ){
         max = z;
      }
      return max;
   }
public static void main( String args[] ) { System.out.printf( "%d, %d 和 %d 中最大的数为 %d\n\n", 3, 4, 5, maximum( 3, 4, 5 ) ); System.out.printf( "%.1f, %.1f 和 %.1f 中最大的数为 %.1f\n\n", 6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ) ); System.out.printf( "%s, %s 和 %s 中最大的数为 %s\n","pear", "apple", "orange", maximum( "pear", "apple", "orange" ) ); } }

 

  • 泛型类
public class Box<T> { private T t;
 
  public void add(T t) {
    this.t = t;
  }
 
  public T get() {
    return t;
  }
 
  public static void main(String[] args) {
    Box<Integer> integerBox = new Box<Integer>();
    Box<String>  stringBox  = new Box<String>();
 
    integerBox.add(new Integer(10));
    stringBox.add(new String("菜鸟教程"));
 
    System.out.printf("整型值为 :%d\n\n", integerBox.get());
    System.out.printf("字符串为 :%s\n", stringBox.get());
  }
}

   

  • 类型通配符

Ref: Java 泛型总结(三):通配符的使用

意义:通配符的使用能够对泛型参数作出某些限制,使代码更安全!

一个数组override的例子:

    • 对于编译器来讲,这是能够经过编译的,
    • 在运行时期,JVM 可以知道数组的实际类型是 Apple[],因此当其它对象加入数组的时候就会抛出异常。
class Fruit {}
class Apple    extends Fruit {}
class Jonathan extends Apple {}
class Orange   extends Fruit {}

public class CovariantArrays {
    public static void main(String[] args) {   
Fruit[] fruit
= new Apple[10]; // 数组的协变,这是一种缺陷?
// ArrayList<Fruit> flist = new ArrayList<Apple>();
fruit[
0] = new Apple(); // OK fruit[1] = new Jonathan(); // OK ... ...
} }

当涉及到泛型时, 尽管 Apple 是 Fruit 的子类型,可是 ArrayList<Apple> 不是 ArrayList<Fruit> 的子类型,泛型不支持协变。 

若是咱们确实须要创建这种 “向上转型” 的关系怎么办呢?这就须要通配符来发挥做用了。 

 

上边界限定通配符

List<? extends Fruit> flist = new ArrayList<Apple>();

如今,咱们并不关心这个实际的类型究竟是什么,反正是 Fruit 的子类型,Fruit 是它的上边界

在上面的代码中,向 flist 中添加任何对象,不管是 Apple 仍是 Orange 甚至是 Fruit 对象,编译器都不容许,惟一能够添加的是 null

因此,若是作了泛型的向上转型,那么咱们也就失去了向这个 List 添加任何对象的能力,即便是 Object 也不行。

 

然而,add() 接受一个泛型类型做为参数;

可是,contains 和 indexOf 接受一个Object类型的参数。

public boolean add     (E e)
public boolean contains(Object o)
public int     indexOf (Object o)

因此,本身编写类时【替代如上的List】,方法所有定义为泛型,就能够支持上边界限定通配符了。

 

下边界限定通配符

public class SuperTypeWildcards {
    static void writeTo(List<? super Apple> apples) {
        apples.add(new Apple());
        apples.add(new Jonathan());
        // apples.add(new Fruit()); // Error,Fruit是Apple的父类!
    }
}

以下,只要是T的父类,均可以copy()。

public class Collections { 
  public static <T> void copy(List<? super T> dest, List<? extends T> src) 
  {
    for (int i=0; i<src.size(); i++) {
      dest.set(i, src.get(i)); 
    }   } }

 

无边界通配符

List<?>,也就是没有任何限定。不作任何限制,跟不用类型参数的 List 有什么区别呢?

List<?> list 表示 list 是持有某种特定类型的 List,可是不知道具体是哪一种类型。那么咱们能够向其中添加对象吗?固然不能够!

由于并不知道实际是哪一种类型,因此不能添加任何类型,这是不安全的。

单独的 List list,也就是没有传入泛型参数,表示这个 list 持有的元素的类型是 Object,所以能够添加任何类型的对象,只不过编译器会有警告信息。

【如此说来,貌似没什么大用】

 

 

Java 序列化

优缺点比较:

  优势 缺点
Serializable 使用方便,可序列化全部类 速度慢,占空间
Protostuff 速度快,基于protobuf 需静态编译

一个类的对象要想序列化成功,必须知足两个条件:

    • 该类必须实现 java.io.Serializable 对象。
    • 该类的全部属性必须是可序列化的。若是有一个属性不是可序列化的,则该属性必须注明是短暂的。

 

SerializeDemo.java 

import java.io.*;
 
public class SerializeDemo
{
   public static void main(String [] args)
   {
      Employee e = new Employee();
      e.name    = "Reyan Ali";
      e.address = "Phokka Kuan, Ambehta Peer";
      e.SSN     = 11122333;
      e.number  = 101;
      try
      {
         FileOutputStream fileOut = new FileOutputStream("/tmp/employee.ser");
         ObjectOutputStream out = new ObjectOutputStream(fileOut);
         out.writeObject(e);
         out.close();
         fileOut.close();
         System.out.printf("Serialized data is saved in /tmp/employee.ser");
      }catch(IOException i)
      {
          i.printStackTrace();
      }
   }
}

DeserializeDemo.java

import java.io.*;
 
public class DeserializeDemo
{
   public static void main(String [] args)
   {
      Employee e = null;
      try
      {
         FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
         ObjectInputStream in   = new ObjectInputStream(fileIn);
         e = (Employee) in.readObject();
         in.close();
         fileIn.close();
      }catch(IOException i)
      {
         i.printStackTrace();
         return;
      }catch(ClassNotFoundException c)
      {
         System.out.println("Employee class not found");
         c.printStackTrace();
         return;
      }
      System.out.println("Deserialized Employee...");
      System.out.println("Name: " + e.name);
      System.out.println("Address: " + e.address);
      System.out.println("SSN: " + e.SSN);
      System.out.println("Number: " + e.number);
    }
}

 

 

Java 网络编程

客户端:经过 socket 链接到服务器并发送一个请求,而后等待一个响应。

// 文件名 GreetingClient.java
 
import java.net.*;
import java.io.*;
 
public class GreetingClient
{
   public static void main(String [] args)
   {
      String serverName = args[0];
      int    port       = Integer.parseInt(args[1]);
      try
      {
         System.out.println("链接到主机:" + serverName + " ,端口号:" + port);
Socket client
= new Socket(serverName, port);   // Create socket System.out.println("远程主机地址:" + client.getRemoteSocketAddress()); OutputStream outToServer = client.getOutputStream();   // Create stream channel at local DataOutputStream out = new DataOutputStream(outToServer);   // Create data channel at local out.writeUTF("Hello from " + client.getLocalSocketAddress()); // <---- 发数据 InputStream inFromServer = client.getInputStream(); // <---- Create stream channel at local 等回应 DataInputStream in = new DataInputStream(inFromServer); System.out.println("服务器响应: " + in.readUTF()); client.close(); }catch(IOException e) { e.printStackTrace(); } } }

 

服务端:使用 Socket 来监听一个指定的端口。

// 文件名 GreetingServer.java
 
import java.net.*;
import java.io.*;
 
public class GreetingServer extends Thread
{
   private ServerSocket serverSocket;
   
   public GreetingServer(int port) throws IOException
   {
      serverSocket = new ServerSocket(port);
      serverSocket.setSoTimeout(10000);
   }
 
   public void run()
   {
      while(true)
      {
         try
         {
            System.out.println("等待远程链接,端口号为:" + serverSocket.getLocalPort() + "...");
            Socket server = serverSocket.accept();
            System.out.println("远程主机地址:" + server.getRemoteSocketAddress());
            DataInputStream in = new DataInputStream(server.getInputStream());  // ----> 先stream 后data
            System.out.println(in.readUTF());
DataOutputStream out
= new DataOutputStream(server.getOutputStream());  // ----> 准备应答,先stream 后data out.writeUTF("谢谢链接我:" + server.getLocalSocketAddress() + "\nGoodbye!"); server.close(); }catch(SocketTimeoutException s) { System.out.println("Socket timed out!"); break; }catch(IOException e) { e.printStackTrace(); break; } } }
public static void main(String [] args) { int port = Integer.parseInt(args[0]); try { Thread t = new GreetingServer(port);  // Create thread to listen t.run(); }catch(IOException e) { e.printStackTrace(); } } }

 

 

Java 发送邮件

略,详见连接

 

Java 多线程编程

 

Java 提供了三种建立线程的方法:

    1. 经过实现 Runnable 接口
    2. 经过继承 Thread 自己;
    3. 经过 Callable 和 Future 建立线程。

(1).

class RunnableDemo implements Runnable {
private Thread t; private String threadName; RunnableDemo( String name) { threadName = name; System.out.println("Creating " + threadName ); } public void run() {   // 运行状态 System.out.println("Running " + threadName ); try { for(int i = 4; i > 0; i--) { System.out.println("Thread: " + threadName + ", " + i); // 让线程睡眠一会 Thread.sleep(50); } }catch (InterruptedException e) { System.out.println("Thread " + threadName + " interrupted."); } System.out.println("Thread " + threadName + " exiting."); } public void start() {  // 就绪状态 System.out.println("Starting " + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); } } } public class TestThread { public static void main(String args[]) { RunnableDemo R1 = new RunnableDemo( "Thread-1"); R1.start();  // ----> 进入就绪状态 RunnableDemo R2 = new RunnableDemo( "Thread-2"); R2.start(); } }

  

(2). 

与上述在写法上没什么大区别。

Thread原本就是实现了Runnable,包含Runnable的功能是很正常的啊!!至于二者的真正区别最主要的就是一个是继承,一个是实现;

还有一些面向对象的思想,

    • Runnable就至关于一个做业,
    • Thread才是真正的处理线程,

咱们须要的只是定义这个做业,而后将做业交给线程去处理,这样就达到了松耦合,也符合面向对象里面组合的使用,

另外也节省了函数开销,继承Thread的同时,不只拥有了做业的方法run(),还继承了其余全部的方法

综合来看,用Runnable比Thread好的多。

class ThreadDemo extends Thread { private Thread t;
   private String threadName;
   
   ThreadDemo( String name) {
      threadName = name;
      System.out.println("Creating " +  threadName );
   }
   
   public void run() {   // ----> 重写该类的run()方法,线程的执行体
      ... ...
   }
   
   public void start() {
      ... ...
} public class TestThread {
 
   public static void main(String args[]) {
      ThreadDemo T1 = new ThreadDemo( "Thread-1");
      T1.start();
      
      ThreadDemo T2 = new ThreadDemo( "Thread-2");
      T2.start();
   }   
}

  

(3). 

Java5策略 - 裸线程的进步callable

Ref:Java线程(七):Callable和Future

Callable和Future,一个产生结果,一个拿到结果。 

Callable接口相似于Runnable,

    • 可是Runnable不会返回结果,而且没法抛出返回结果的异常,
    • 而Callable功能更强大一些,被线程执行后,能够返回值,这个返回值能够被Future拿到,也就是说,Future能够拿到异步执行任务的返回值。

Callable接口提供了一个call()方法做为线程执行体,call()方法比run()方法功能要强大,能够有返回值!

Java5提供了Future接口来表明Callable接口里call()方法的返回值。

 

FutureTask实现了两个接口,Runnable和Future,因此

    • 它既能够做为Runnable被线程执行
    • 又能够做为Future获得Callable的返回值
public class CallableAndFuture {
public static void main(String[] args) {
Callable
<Integer> callable = new Callable<Integer>() { public Integer call() throws Exception {        // ----> call做为线程执行体,且能够有返回值 return new Random().nextInt(100); } };

/*
* 1. callable是个类的实例,里面定义了线程执行体函数call()。
* 2. future这个类来表明callable所表明线程的返回值。
*/ FutureTask
<Integer> future = new FutureTask<Integer>(callable);  // ----> Future接口表明 Callable接口里call()方法的返回值
/* 3. 准备就绪,线程start */
new Thread(future).start();
try { Thread.sleep(5000);// 可能作一些事情 System.out.println(future.get());  // <---- 获得返回值 } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }

 

Java5以后的策略 - Executor框架

简化并发编程,Executor使咱们无需显式地去管理线程的生命周期,是JDK 5以后启动任务的首选方式。

Ref:Java并发的四种风味:Thread、Executor、ForkJoin和Actor

Ref:java并发编程--Executor框架

Executor接口的定义很是简单:

public interface Executor {
  void execute(Runnable command);
}

 

  • Executor:一个接口,其定义了一个接收Runnable对象的方法executor,其方法签名为executor(Runnable command), 
  • ExecutorService是一个比Executor使用更普遍的子类接口,其提供了生命周期管理的方法,以及可跟踪一个或多个异步任务执行情况返回Future的方法
  • AbstractExecutorService:ExecutorService执行方法的默认实现 
  • ScheduledExecutorService:一个可定时调度任务的接口
  • ScheduledThreadPoolExecutor:ScheduledExecutorService的实现,一个可定时调度任务的线程池
  • ThreadPoolExecutor线程池,能够经过调用Executors如下静态工厂方法来建立线程池并返回一个ExecutorService对象:

 

线程池例子:任务执行完成后并返回执行结果

public class CallableAndFuture {
public static void main(String[] args) {
ExecutorService threadPool
= Executors.newSingleThreadExecutor();   // ExecutorService继承自Executor,管理Thread对象 Future<Integer> future = threadPool.submit(new Callable<Integer>() {  // 线程池的线程提供了获取返回值future的服务。 public Integer call() throws Exception {   // 线程的执行体 return new Random().nextInt(100); } });
try { Thread.sleep(5000);// 可能作一些事情 System.out.println(future.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }

 

例1:使用newScheduledThreadPool来模拟心跳机制

public class HeartBeat {
    public static void main(String[] args) {
ScheduledExecutorService executor
= Executors.newScheduledThreadPool(5);  // <---- 有五个线程的线程池
Runnable task
= new Runnable() { public void run() { System.out.println("HeartBeat........................."); } };
executor.scheduleAtFixedRate(task,
5,3, TimeUnit.SECONDS); //5秒后第一次执行,以后每隔3秒执行一次 } }

 

例2:线程能够重用,节省资源  

public class ThreadPoolTest {
    public static void main(String[] args) throws InterruptedException {
ExecutorService threadPool
= Executors.newCachedThreadPool();//线程池里面的线程数会动态变化,并可在线程线被移除前重用

for (int i = 1; i <= 3; i ++) { final int task = i;//TimeUnit.SECONDS.sleep(1);  // 第六行! threadPool.execute(new Runnable() { //接受一个Runnable实例 public void run() { System.out.println("线程名字: " + Thread.currentThread().getName() + " 任务名为: "+task); } }); } } }

输出结果:

// 输出:(为每一个任务新建一条线程,共建立了3条线程)
线程名字: pool-1-thread-1 任务名为: 1
线程名字: pool-1-thread-2 任务名为: 2
线程名字: pool-1-thread-3 任务名为: 3

// 去掉第6行的注释其输出以下:(始终重复利用一条线程,由于newCachedThreadPool能重用可用线程) 线程名字: pool-1-thread-1 任务名为: 1 线程名字: pool-1-thread-1 任务名为: 2 线程名字: pool-1-thread-1 任务名为: 3

 

例3:启动10条线程,谁先执行完成就返回谁

CompletionService:将执行完成的任务放到阻塞队列中,经过take或poll方法来得到执行结果。

public class CompletionServiceTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executor
= Executors.newFixedThreadPool(10); //建立含10条线程的线程池 CompletionService completionService = new ExecutorCompletionService(executor);
for (int i =1; i <=10; i ++) { final int result = i; completionService.submit(new Callable() { public Object call() throws Exception { Thread.sleep(new Random().nextInt(5000)); //让当前线程随机休眠一段时间 return result; } }); }
System.out.println(completionService.take().get());
//获取执行结果 } }
输出结果可能每次都不一样(在1到10之间)。
经过Executor来设计应用程序能够简化开发过程,提升开发效率,并有助于实现并发,在开发中若是须要建立线程可优先考虑使用Executor

 

Java Applet 基础

略,已被js取代。

 

Java 文档注释

javadoc 工具将你 Java 程序的源代码做为输入,输出一些包含你程序注释的HTML文件。

详见连接

 

Java 实例

功能代码demo参考,详见连接。 

 

Java 8 新特性

编程风格的不一样:

 import java.util.Collections;   

// 使用 java 7 排序 private void sortUsingJava7(List<String> names){ Collections.sort(names, new Comparator<String>() { @Override public int compare(String s1, String s2) { return s1.compareTo(s2); } }); }
// 上面的compare名字其实不重要
// 也就侧面说明了匿名函数的必要性
// 使用 java 8 排序 private void sortUsingJava8(List<String> names){ Collections.sort(names, (s1, s2) -> s1.compareTo(s2)); }

其余详见:http://www.runoob.com/java/java8-new-features.html

 

Java MySQL 链接

使用 JDBC 链接 MySQL 数据库。

Java 链接 MySQL 须要驱动包,最新版下载地址为:http://dev.mysql.com/downloads/connector/j/,解压后获得jar库文件,而后在对应的项目中导入该库文件。

package com.runoob.test;
import java.sql.*;
 
public class MySQLDemo {
 
    // JDBC 驱动名及数据库 URL
    static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";  
    static final String DB_URL      = "jdbc:mysql://localhost:3306/RUNOOB";
 
    // 数据库的用户名与密码,须要根据本身的设置
    static final String USER = "root";
    static final String PASS = "123456";
 
public static void main(String[] args) { Connection conn = null; Statement stmt = null;
try{ // 1. 注册 JDBC 驱动 Class.forName("com.mysql.jdbc.Driver"); // 2. 打开连接 System.out.println("链接数据库..."); conn = DriverManager.getConnection(DB_URL,USER,PASS); // 3. 执行查询 System.out.println(" 实例化Statement对象..."); stmt = conn.createStatement(); String sql; sql = "SELECT id, name, url FROM websites"; ResultSet rs = stmt.executeQuery(sql); // 展开结果集数据库 while(rs.next()){ // 经过字段检索 int id = rs.getInt("id"); String name = rs.getString("name"); String url = rs.getString("url"); // 输出数据 System.out.print("ID: " + id); System.out.print(", 站点名称: " + name); System.out.print(", 站点 URL: " + url); System.out.print("\n"); } // 完成后关闭 rs.close(); stmt.close(); conn.close();
}
catch(SQLException se){ // 处理 JDBC 错误 se.printStackTrace();
}
catch(Exception e){ // 处理 Class.forName 错误 e.printStackTrace();
}
finally{ // 关闭资源 try{ if(stmt!=null)
stmt.close(); }
catch(SQLException se2){
}
// 什么都不作
try{ if(conn!=null) conn.close(); }catch(SQLException se){ se.printStackTrace(); } } System.out.println("Goodbye!"); } }

 

 

补充

Ref:java面试57道题,转自知乎某位知友 

相关文章
相关标签/搜索