java 有c基础的自学教程(全站最详细 没有之一)

0.简介

快捷键https://www.jianshu.com/p/c31a934080a3

新建.java 文件 文件名与类名保持一致

特别地,Java 语言不使用指针,而是引用。并提供了自动分配和回收内存空间,使得程序员不必为内存管理而担忧。

单继承:一个子类只能有一个直接父类。 多继承:一个子类可以有多个直接父类。

java为了避免多继承导致的问题取消了多继承。

 java中的main方法是java应用程序的入口,java程序在运行时,首先调用执行main方法。但并不是说java中只能有一个main方法,不同类中都可以包含main方法。当JVM进行编译时,会提示选择其中一个main方法作为编译的入口。

# 一.基础

## 1.基础语法

- **类名**:对于所有的类来说,类名的首字母应该大写。如果类名由若干单词组成,那么每个单词的首字母应该大写,例如 **MyFirstJavaClass** 。
- **方法名**:(函数)所有的方法名都应该以小写字母开头。如果方法名含有若干单词,则后面的每个单词首字母大写。

- **主方法入口**:所有的 Java 程序由 **public static void main(String[] args)** 方法开始执行。

## 2.对象与类

```
/* 实例化对象 */
Object referenceVariable = new Constructor();
```

 静态变量是全局变量(类变量),被所有类的实例对象共享,即一个实例的改变了静态变量的值,其他同类的实例读到的就是变化后的值; 非静态变量是局部变量,不共享,即一个类的不同实例访问的非静态变量可以是不同的值。

一些细节

```
一个源文件中只能有一个 public 类
一个源文件可以有多个非 public 类
源文件的名称应该和 public 类的类名保持一致。例如:源文件中 public 类的类名是 Employee,那么源文件应该命名为Employee.java。
如果一个类定义在某个包中,那么 package 语句应该在源文件的首行。
如果源文件包含 import 语句,那么应该放在 package 语句和类定义之间。如果没有 package 语句,那么 import 语句应该在源文件中最前面。
import 语句和 package 语句对源文件中定义的所有类都有效。在同一源文件中,不能给不同的类不同的包声明。
```

## 3.lambda表达式

```
(parameters) -> expression

(parameters) ->{ statements; 
```

```
// 1. 不需要参数,返回值为 5  
() -> 5  
  
// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  
  
// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  
  
// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  
  
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)
```

一个例子:

```
public class Java8Tester {
   public static void main(String args[]){
      Java8Tester tester = new Java8Tester();
        
      // 类型声明
      MathOperation addition = (int a, int b) -> a + b;
        
      // 不用类型声明
      MathOperation subtraction = (a, b) -> a - b;
        
      // 大括号中的返回语句
      MathOperation multiplication = (int a, int b) -> { return a * b; };
        
      // 没有大括号及返回语句
      MathOperation division = (int a, int b) -> a / b;
        
      System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
      System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
      System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
      System.out.println("10 / 5 = " + tester.operate(10, 5, division));
        
      // 不用括号
      GreetingService greetService1 = message ->
      System.out.println("Hello " + message);
        
      // 用括号
      GreetingService greetService2 = (message) ->
      System.out.println("Hello " + message);
        
      greetService1.sayMessage("Runoob");
      greetService2.sayMessage("Google");
   }
    
   interface MathOperation {
      int operation(int a, int b);
   }
    
   interface GreetingService {
      void sayMessage(String message);
   }
    
   private int operate(int a, int b, MathOperation mathOperation){
      return mathOperation.operation(a, b);
   }
}
```

## 

## 4.基本数据类型

byte:8位的整数 short int long 

char比较特殊

```
char:

char 类型是一个单一的 16 位 Unicode 字符;
最小值是 \u0000(十进制等效值为 0);
最大值是 \uffff(即为 65535);
char 数据类型可以储存任何字符;
例子:char letter = 'A';。
```

引用类型:

- 在Java中,引用类型的变量非常类似于C/C++的指针。引用类型指向一个对象,指向对象的变量是引用变量。这些变量在声明时被指定为一个特定的类型,比如 Employee、Puppy 等。变量一旦声明后,类型就不能被改变了。

常量

```
final double PI = 3.1415927;
```

/u0001 代表unicode字符

![image-20211003094714376](C:\Users\18303\AppData\Roaming\Typora\typora-user-images\image-20211003094714376.png)

一些代表

全局变量和局部变量的一些存储方式

```
C语言经过编译之后将内存分为以下几个区域:


(1)栈(stack):由编译器进行管理,自动分配和释放,存放函数调用过程中的各种参数、局部变量、返回值以及函数返回地址。操作方式类似数据结构中的栈。


(2)堆(heap):用于程序动态申请分配和释放空间。C语言中的malloc和free,C++中的new和delete均是在堆中进行的。正常情况下,程序员申请的空间在使用结束后应该释放,若程序员没有释放空间,则程序结束时系统自动回收。注意:这里的“堆”并不是数据结构中的“堆”。


(3)全局(静态)存储区:分为DATA段和BSS段。DATA段(全局初始化区)存放初始化的全局变量和静态变量;BSS段(全局未初始化区)存放未初始化的全局变量和静态变量。程序运行结束时自动释放。其中BBS段在程序执行之前会被系统自动清0,所以未初始化的全局变量和静态变量在程序执行之前已经为0。


(4)文字常量区:存放常量字符串。程序结束后由系统释放。


(5)程序代码区:存放程序的二进制代码。

```

静态变量可以通过类名来访问

## 5. 修饰符

**protected** 是只有子类可以访问,介于private和public之间

eg

```
class AudioPlayer {
   protected boolean openSpeaker(Speaker sp) {
      // 实现细节
   }
}
 
class StreamingAudioPlayer extends AudioPlayer {
   protected boolean openSpeaker(Speaker sp) {
      // 实现细节
   }
}
```

**abstract 修饰符**

**抽象类:**

抽象类不能用来实例化对象,声明抽象类的唯一目的是为了将来对该类进行扩充。

**volatile 修饰符**

volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。

## 6.运算符

也有条件运算符?:

instanceof运算符

```
String name = "James";
boolean result = name instanceof String; // 由于 name 是 String 类型,所以返回真
```

## 7.循环

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(",");
      }
      System.out.print("\n");
      String [] names ={"James", "Larry", "Tom", "Lacy"};
      for( String name : names ) {
         System.out.print( name );
         System.out.print(",");
      }
   }
}
```

## 8.switch case

如果 case 语句块中没有 break 语句时,匹配成功后,从当前 case 开始,后续所有 case 的值都会输出。

## 9.内置num/math类

注意装箱拆箱操作

内置num类character类有自己的方法

eg:valueof intval...

```
装箱与拆箱

public class Main {
    public static void main(String[] args) {
         
        Integer i = 10;
        int n = i;
    }
}
从反编译得到的字节码内容可以看出,在装箱的时候自动调用的是Integer的valueOf(int)方法。而在拆箱的时候自动调用的是Integer的intValue方法。
-128~127有cache
```

![image-20211003104821968](C:\Users\18303\AppData\Roaming\Typora\typora-user-images\image-20211003104821968.png)

![image-20211003105253378](C:\Users\18303\AppData\Roaming\Typora\typora-user-images\image-20211003105253378.png)

![image-20211003105409778](C:\Users\18303\AppData\Roaming\Typora\typora-user-images\image-20211003105409778.png)

上面是生成class 下面是生成反汇编码

## 10.string StringBuffer & StringBuilder 类

![image-20211003113319457](C:\Users\18303\AppData\Roaming\Typora\typora-user-images\image-20211003113319457.png)

string类一旦创建就无法改变

如果需要对字符串做很多修改,那么应该选择使用 StringBuffer & StringBuilder 类。

```
public class RunoobTest{
    public static void main(String args[]){
        StringBuilder sb = new StringBuilder(10);
        sb.append("Runoob..");
        System.out.println(sb);  
        sb.append("!");
        System.out.println(sb); 
        sb.insert(8, "Java");
        System.out.println(sb); 
        sb.delete(5,8);
        System.out.println(sb);  
    }
}
```

然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。

## 11.数组

创建方式

```
double[] myList = {1.9, 2.9, 3.4, 3.5};


int size = 10;
      // 定义数组
double[] myList = new double[size];
```

```
dataType[] arrayRefVar;   // 首选的方法
 

 
dataType arrayRefVar[];  // 效果相同,但不是首选方法
```

Arrays 类

java.util.Arrays 类能方便地操作数组,它提供的所有方法都是静态的。

具有以下功能:

- 给数组赋值:通过 fill 方法。
- 对数组排序:通过 sort 方法,按升序。
- 比较数组:通过 equals 方法比较数组中元素值是否相等。
- 查找数组元素:通过 binarySearch 方法能对排序好的数组进行二分查找法操作。

## 12.日期时间

```
import java.util.Date;
  
public class DateDemo {
   public static void main(String args[]) {
       // 初始化 Date 对象
       Date date = new Date();
        
       // 使用 toString() 函数显示日期时间
       System.out.println(date.toString());
   }
}
```

import的用法

自定义日期的格式

```
import  java.util.*;
import java.text.*;
 
public class DateDemo {
   public static void main(String args[]) {
 
      Date dNow = new Date( );
      SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");
 
      System.out.println("当前时间为: " + ft.format(dNow));
   }
}
```

可能用于写日志?有很多的格式和表达形式。

计算机时间的休眠

```
import java.util.*;

public class SleepDemo {
    public static void main(String args[]) {
        try {
            System.out.println(new Date( ) + "\n");
            Thread.sleep(1000*3);   // 休眠3秒
            System.out.println(new Date( ) + "\n");
        } catch (Exception e) {
            System.out.println("Got an exception!");
        }
    }
}
```

Calendar类

Calendar类是一个抽象类,在实际使用时实现特定的子类的对象,创建对象的过程对程序员来说是透明的,只需要使用**getInstance**方法创建即可。

关于getinstance

```
单例模式 可以防止 数据的冲突,节省内存空间
getInstance在单例模式(保证一个类仅有一个实例,并提供一个访问它的访问点)的类中常见,用来生成唯一的实例,getInstance往往是static的。
```

## 13.输入输出流(I/O input&output)

```
import java.io.*;
public class StandardInputOutput {
    public static void main(String args[]) {
        int b;
        try {
            System.out.println("please Input:");
            while ((b = System.in.read()) != -1) {
                System.out.print((char) b);
            }
        } catch (IOException e) {
            System.out.println(e.toString());
        }
    }
}
```

**读取单个的字符**

```
//使用 BufferedReader 在控制台读取字符

import java.io.*;

public class BRRead {
    public static void main(String[] args) throws IOException {
        char c;
        // 使用 System.in 创建 BufferedReader
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("输入字符, 按下 'q' 键退出。");
        // 读取字符
        do {
            c = (char) br.read();
            System.out.println(c);
        } while (c != 'q');
    }
}
```

读取一行的内容

```
//使用 BufferedReader 在控制台读取字符
import java.io.*;
 
public class BRReadLines {
    public static void main(String[] args) throws IOException {
        // 使用 System.in 创建 BufferedReader
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String str;
        System.out.println("Enter lines of text.");
        System.out.println("Enter 'end' to quit.");
        do {
            str = br.readLine();
            System.out.println(str);
        } while (!str.equals("end"));
    }
}
```

注意这边是equal不是=

补充:

1.字节流和字符流

1byte=8bit 1 char =16 bit

**总而言之,一切都是字节流,其实没有字符流这个东西。字符只是根据编码集对字节流翻译之后的产物**

总而言之,一切都是字节流,其实没有字符流这个东西。字符只是根据编码集对字节流翻译之后的产物

parser是收到utf8的字节后去掉utf-8报头包装成unicode返回

write()则是一个相反的过程

**字节流就是普通的二进制流,读出来的是bit**
**字符流就是在字节流的基础按照字符编码处理,处理的是char**

2.字符编码问题:

> acsii 一字节 最前面一位是0 后面可以表示128个符号 对应英语字符和二进制位之间的关系

> 非ascii编码  一些欧洲国家 利用字节中限制的最高位编入新的符号0——127位是一样的,不一样的是后面的一半
>
> 但简体中文的编码方式就更加复杂了,GB2312是常见的中文编码方式 这里先不涉及 这类编码方式与unicode 和utf-8毫无关系

> 可以想象,如果有一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码,那么乱码问题就会消失。这就是 Unicode,就像它的名字都表示的,这是一种所有符号的编码。
>
> ```
> cout<<"\u1F01"< > ```
>
> 上面是C++中输出unicode的方法
>
> 去掉+ 将u改为小写
>
> 但unicode 不能让计算机知道三个字节代表一个符号 而且会造成空间的浪费

> utf-8是互联网上最常用的一种unicode的实现方式
>
> ```
> UTF-8 的编码规则很简单,只有二条:

> 1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。

> 2)对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。
> ```
>
> ![image-20211006112113143](C:\Users\18303\AppData\Roaming\Typora\typora-user-images\image-20211006112113143.png)

> 可以用notepad进行字符编码的转化
>
> `ANSI`是默认的编码方式。对于英文文件是`ASCII`编码,对于简体中文文件是`GB2312`编码(只针对 Windows 简体中文版,如果是繁体中文版会采用 Big5 码)。

> 还有大端小端的一些问题

文件读写例子:

```
import java.io.*;
 
public class fileStreamTest {
    public static void main(String[] args) {
        try {
            byte bWrite[] = { 11, 21, 3, 40, 5 };
            OutputStream os = new FileOutputStream("test.txt");
            for (int x = 0; x < bWrite.length; x++) {
                os.write(bWrite[x]); // writes the bytes
            }
            os.close();
 
            InputStream is = new FileInputStream("test.txt");
            int size = is.available();
 
            for (int i = 0; i < size; i++) {
                System.out.print((char) is.read() + "  ");
            }
            is.close();
        } catch (IOException e) {
            System.out.print("Exception");
        }
    }
}
```

## 14.正则表达式

正则表达式的常用写法

```
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);
   }
}
```

正则表达式的start end 方法

```
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class RegexMatches
{
    private static final String REGEX = "\\bcat\\b";
    private static final String INPUT =
                                    "cat cat cat cattie cat";
 
    public static void main( String[] args ){
       Pattern p = Pattern.compile(REGEX);
       Matcher m = p.matcher(INPUT); // 获取 matcher 对象
       int count = 0;
 
       while(m.find()) {
         count++;
         System.out.println("Match number "+count);
         System.out.println("start(): "+m.start());
         System.out.println("end(): "+m.end());
      }
   }
}
```

注意正则表达式内转移符号的特殊表达

```
在 Java 中,\\ 表示:我要插入一个正则表达式的反斜线,所以其后的字符具有特殊的意义。

所以,在其他的语言中(如 Perl),一个反斜杠 \ 就足以具有转义的作用,而在 Java 中正则表达式中则需要有两个反斜杠才能被解析为其他语言中的转义作用。也可以简单的理解在 Java 的正则表达式中,两个 \\ 代表其他语言中的一个 \,这也就是为什么表示一位数字的正则表达式是 \\d,而表示一个普通的反斜杠是 \\。
```

appendReplacement 和 appendTail 方法

replaceFirst 和 replaceAll 方法

matches 和 lookingAt 方法

## 15.java方法

## 16.scanner类

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

```
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();
    }
}
```

连续输入 求平均值的一个程序

```
import java.util.Scanner;
 
class RunoobTest {
    public static void main(String[] args) {
        System.out.println("请输入数字:");
        Scanner scan = new Scanner(System.in);
 
        double sum = 0;
        int m = 0;
 
        while (scan.hasNextDouble()) {
            double x = scan.nextDouble();
            m = m + 1;
            sum = sum + x;
        }
 
        System.out.println(m + "个数的和为" + sum);
        System.out.println(m + "个数的平均值是" + (sum / m));
        scan.close();
    }
}
```

## 17.异常处理

try...catch块 还可以加上finally关键词,无论什么情况下善后执行

```
// 文件名 : 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");
   }
}
```

if...else{  throw  }块

throw一般是一个另外定义的类

# 二.面向对象

## 18.继承

```
class 父类 {
}
 
class 子类 extends 父类 {
}
```

java不支持多继承(不能有多个父亲)

一些标识符:

使用 implements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)。

super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。

this关键字:指向自己的引用。

final关键字

final 关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写:

**注**:实例变量也可以被定义为 final,被定义为 final 的变量不能被修改。被声明为 final 类的方法自动地声明为 final,但是实例变量并不是 final

构造函数

如果父类构造器没有参数,则在子类的构造器中不需要使用 **super** 关键字调用父类构造器,系统会自动调用父类的无参构造器

## 19.重写(override)重载(overload)

**重写:**

重写是**子类对父类的允许访问的方法**的实现过程进行重新编写, 返回值和形参都不能改变。**即外壳不变,核心重写!**

**重载:**

重载(overloading) 是**在一个类里面**,方法名字相同,而参数不同。返回类型可以相同也可以不同。

每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。

## 20.接口

```
接口与类相似点:
一个接口可以有多个方法。
接口文件保存在 .java 结尾的文件中,文件名使用接口名。
接口的字节码文件保存在 .class 结尾的文件中。
接口相应的字节码文件必须在与包名称相匹配的目录结构中。
接口与类的区别:
接口不能用于实例化对象。
接口没有构造方法。
接口中所有的方法必须是抽象方法,Java 8 之后 接口中可以使用 default 关键字修饰的非抽象方法。
接口不能包含成员变量,除了 static 和 final 变量。
接口不是被类继承了,而是要被类实现。
接口支持多继承。
```

接口默认是abstarct的,接口也可以继承

一个类implement接口的时候要实现接口中的所有方法

接口与抽象类比特殊的地方是接口可以实现多继承

## 21.java package

**package**

(开个文件夹看着舒服点的一种良好的组织形式)

以下是一些 Java 中的包:

- **java.lang**-打包基础的类
- **java.io**-包含输入输出功能的函数

为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间。

个人理解package大概就是组织成一种树状的结构

如果其他的源文件包括了这个包提供的类接口的时候,就必须把这个包的生命放在源文件的开头

**import**

调用其他包中的内容

可以用很多

三.高级

22.一些数据结构

import java.util.Vector
​
or
​
import java.util.*;
  • bitset用来执行布尔操作

  • properties类

Properties 继承于 Hashtable。表示一个持久的属性集.属性列表中每个键及其对应值都是一个字符串。

Properties 类被许多 Java 类使用。例如,在获取环境变量时它就作为 System.getProperties() 方法的返回值。

一个例子

import java.util.*;
 
public class PropDemo {
 
   public static void main(String args[]) {
      Properties capitals = new Properties();
      Set states;
      String str;
      
      capitals.put("Illinois", "Springfield");
      capitals.put("Missouri", "Jefferson City");
      capitals.put("Washington", "Olympia");
      capitals.put("California", "Sacramento");
      capitals.put("Indiana", "Indianapolis");
 
      // Show all states and capitals in hashtable.
      states = capitals.keySet(); // get set-view of keys
      Iterator itr = states.iterator();
      while(itr.hasNext()) {
         str = (String) itr.next();
         System.out.println("The capital of " +
            str + " is " + capitals.getProperty(str) + ".");
      }
      System.out.println();
 
      // look for state not in list -- specify default
      str = capitals.getProperty("Florida", "Not Found");
      System.out.println("The capital of Florida is "
          + str + ".");
   }
}

23.泛型

  • extend

eg

public class MaximumTest
{
   // 比较三个值并返回最大值
   public static > T maximum(T x, T y, T z)
   {                     
      T max = x; // 假设x是初始最大值
      if ( y.compareTo( max ) > 0 ){
         max = y; //y 更大
      }
      if ( z.compareTo( max ) > 0 ){
         max = z; // 现在 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 {
   
  private T t;
 
  public void add(T t) {
    this.t = t;
  }
 
  public T get() {
    return t;
  }
 
  public static void main(String[] args) {
    Box integerBox = new Box();
    Box stringBox = new Box();
 
    integerBox.add(new Integer(10));
    stringBox.add(new String("菜鸟教程"));
 
    System.out.printf("整型值为 :%d\n\n", integerBox.get());
    System.out.printf("字符串为 :%s\n", stringBox.get());
  }
}
  • 类型通配符

import java.util.*;
 
public class GenericTest {
     
    public static void main(String[] args) {
        List name = new ArrayList();
        List age = new ArrayList();
        List number = new ArrayList();
        
        name.add("icon");
        age.add(18);
        number.add(314);
 
        getData(name);
        getData(age);
        getData(number);
       
   }
 
   public static void getData(List data) {
      System.out.println("data :" + data.get(0));
   }
}

list在逻辑上是所有list 等具体类型的父类

24.单元测试框架

  • JUnit

JUnit是一个开源的Java语言的单元测试框架,专门针对Java设计,使用最广泛。JUnit是事实上的单元测试的标准框架,任何Java开发者都应当学习并使用JUnit编写单元测试。

25.序列化与反序列化

Java的序列化机制仅适用于Java,如果需要与其它语言交换数据,必须使用通用的序列化方法,例如JSON

26.网络编程

连接建立后,通过使用 I/O 流在进行通信,每一个socket都有一个输出流和一个输入流,客户端的输出流连接到服务器端的输入流,而客户端的输入流连接到服务器端的输出流。

一个有趣的实例

  • Socket 客户端实例

如下的 GreetingClient 是一个客户端程序,该程序通过 socket 连接到服务器并发送一个请求,然后等待一个响应。

GreetingClient.java 文件代码:

// 文件名 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);
         System.out.println("远程主机地址:" + client.getRemoteSocketAddress());
         OutputStream outToServer = client.getOutputStream();
         DataOutputStream out = new DataOutputStream(outToServer);
 
         out.writeUTF("Hello from " + client.getLocalSocketAddress());
         InputStream inFromServer = client.getInputStream();
         DataInputStream in = new DataInputStream(inFromServer);
         System.out.println("服务器响应: " + in.readUTF());
         client.close();
      }catch(IOException e)
      {
         e.printStackTrace();
      }
   }
}
  • Socket 服务端实例

如下的GreetingServer 程序是一个服务器端应用程序,使用 Socket 来监听一个指定的端口。

GreetingServer.java 文件代码:

// 文件名 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());
            System.out.println(in.readUTF());
            DataOutputStream out = new DataOutputStream(server.getOutputStream());
            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);
         t.run();
      }catch(IOException e)
      {
         e.printStackTrace();
      }
   }
}

编译以上两个 java 文件代码,并执行以下命令来启动服务,使用端口号为 6066:

$ javac GreetingServer.java 
$ java GreetingServer 6066
等待远程连接,端口号为:6066...

新开一个命令窗口,执行以上命令来开启客户端:

$ javac GreetingClient.java 
$ java GreetingClient localhost 6066
连接到主机:localhost ,端口号:6066
远程主机地址:localhost/127.0.0.1:6066
服务器响应: 谢谢连接我:/127.0.0.1:6066
Goodbye!

抓IP地址

import java.net.InetAddress;
import java.net.UnknownHostException;
 
public class GetIP {
    public static void main(String[] args) {
        InetAddress address = null;
        try {
            address = InetAddress.getByName("www.runoob.com");
        }
        catch (UnknownHostException e) {
            System.exit(2);
        }
        System.out.println(address.getHostName() + "=" + address.getHostAddress());
        System.exit(0);
    }
}

还可以抓本机的IP和hostname

27.多线程

在多线程编程时,你需要了解以下几个概念:

  • 线程同步

  • 线程间通信

  • 线程死锁

  • 线程控制:挂起、停止和恢复

不过请注意,如果你创建太多的线程,程序执行的效率实际上是降低了,而不是提升了。

请记住,上下文的切换开销也很重要,如果你创建了太多的线程,CPU 花费在上下文的切换的时间将多于执行程序的时间!

28.java applet

Applet或Java小应用程序是一种在Web环境下,运行于客户端的Java程序组件。它也是1990年代中期,Java在诞生后得以一炮走红的功臣之一。通常,每个Applet的功能都比较单一(例如仅用于显示一个舞动的Logo),因此它被称作“小应用程序”1。

Applet必须运行于某个特定的“容器”,这个容器可以是浏览器本身,也可以是通过各种插件,或者包括支持Applet的移动设备在内的其他各种程序来运行。与一般的Java应用程序不同,Applet不是通过main方法来运行的(参见Java的Hello World程序和Java Applet的Hello World程序)。在运行时Applet通常会与用户进行互动,显示动态的画面,并且还会遵循严格的安全检查,阻止潜在的不安全因素(例如根据安全策略,限制Applet对客户端文件系统的访问)。

29.java注释

javadoc 注释

javadoc 输出什么

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

每一个类的信息将在独自的HTML文件里。javadoc 也可以输出继承的树形结构和索引。

由于 javadoc 的实现不同,工作也可能不同,你需要检查你的 Java 开发系统的版本等细节,选择合适的 Javadoc 版本。

一个好玩的例子

下面是一个使用说明注释的简单实例。注意每一个注释都在它描述的项目的前面。
​
在经过 javadoc 处理之后,SquareNum 类的注释将在 SquareNum.html 中找到。
​
import java.io.*;
 
/**
* 这个类演示了文档注释
* @author Ayan Amhed
* @version 1.2
*/
public class SquareNum {
   /**
   * This method returns the square of num.
   * This is a multiline description. You can use
   * as many lines as you like.
   * @param num The value to be squared.
   * @return num squared.
   */
   public double square(double num) {
      return num * num;
   }
   /**
   * This method inputs a number from the user.
   * @return The value input as a double.
   * @exception IOException On input error.
   * @see IOException
   */
   public double getNumber() throws IOException {
      InputStreamReader isr = new InputStreamReader(System.in);
      BufferedReader inData = new BufferedReader(isr);
      String str;
      str = inData.readLine();
      return (new Double(str)).doubleValue();
   }
   /**
   * This method demonstrates square().
   * @param args Unused.
   * @return Nothing.
   * @exception IOException On input error.
   * @see IOException
   */
   public static void main(String args[]) throws IOException
   {
      SquareNum ob = new SquareNum();
      double val;
      System.out.println("Enter value to be squared: ");
      val = ob.getNumber();
      val = ob.square(val);
      System.out.println("Squared value is " + val);
   }
}

30.Java MySQL 连接

JDBC链接

你可能感兴趣的