Java基础恢复(待完善)
2018-05-15 本文已影响23人
平安喜乐698
目录
1. 环境配置(MAC)
1、下载JDK(http://www.oracle.com/technetwork/java/javase/downloads/index.html)
选择JDK版本、下载Mac版本、双击安装包
2、配置环境变量
第一次配置:touch .bash_profile
修改(第二次及以后配置):open -e .bash_profile
编辑内容如下:
JAVA_8_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home
JAVA_9_HOME=/Library/Java/JavaVirtualMachines/jdk9.jdk/Contents/Home
JAVA_HOME=$JAVA_8_HOME
PATH=$JAVA_HOME/bin:$PATH:.
CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:.
export JAVA_HOME
export PATH
export CLASSPATH
3、使配置立即生效
source .bash_profile
查看所有JDK版本下载位置
/Library/Java/JavaVirtualMachines/
查看指定JDK根目录
/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home
bin目录下存放JDK用于开发的一些终端命令工具:
“javac”的作用是将java源文件编译为class文件(即自解码文件);
“java”命令的作用是运行class文件
db目录下是java开发的一个开源的关系型数据库
include目录下是一些C语言的头文件
jre目录下JDK所依赖的java运行时
lib目录下存放JDK开发工具所依赖的一些库文件
man目录下存放JDK开发工具的说明文档
查看当前java版本(jdk版本)
java -version
查看配置的java_home路径
echo $JAVA_HOME


2. 基础
- 标识符
【标识符】:变量、方法、类等命名所使用的字符序列。
命名规则
1、由字母、数字、下划线、$组成
2、以字母、下划线、$开头
3、大小写敏感,长度无限制,不能是关键字(见下图)
约定规则(规范)
见名知意

- 常量与变量
常量
值不可变
整型常量 100
浮点型常量 3.14
字符常量 'a'
逻辑常量 true、false
字符串常量 "hello"
变量
值可变
int x=100;
float f=3.14f;
double d=3.14;
String str="hello";
作用域:
{}内
本质:
声明变量后,在内存中为变量分配一块区域存储变量的值,通过变量名来访问变量的值
分类:
按作用域:
局部变量:方法或语句块内声明的变量
成员变量:方法外类内部声明的变量
按类型:
基本数据类型
引用数据类型
- 运算符和表达式
运算符
算术运算符
+、-、*、/、%、++、--
关系运算符
>=、<=、>、<、=、==、!=
逻辑运算符
&、|、!、^、&&、||
位运算符
&、|、^、~、>>、<<、>>>
赋值运算符
=、+=、-=、*=、/=
字符串拼接符
+
三目运算符
?:
注意:
1、x++ 变量在前则先使用变量再+1
2、&&、||会造成短路(前边的条件不满足则不再判断后面的条件)
表达式
由运算符和操作数组成
表达式的值
对操作数运算后得到的结果
表达式的类型
对操作数运算后得到的结果的类型

- 数据类型

4.1 基本数据类型
整数类型
3种形式:
十进制 1
八进制 01
十六进制 0x12
int x=100;
long l=3000l; // 整型常量默认为int型
数据类型固定的表示范围和字段长度,不受操作系统影响

浮点类型
2种形式:
十进制 1
科学计数法 3.14e2
float f=3.14f; // 浮点型常量默认为double
double d=3.14;
数据类型固定的表示范围和字段长度,不受操作系统影响

char字符型
用单引号括起来的单个字符
char c='a';
char c='\u0061'; // 16进制
char c='\n'; // 转义字符
Unicode编码分为两种,一种是Utf-8,另一种是Utf-16。
JAVA所采用的是Utf-16,每一个字符占2个字节
boolean布尔型
值只能有2种:true、false
boolean flag=true;
if(flag){
}
类型转换(基本数据类型)
boolean类型不能转换为其他数据类型
自动转换(多种数据类型混合运算、=左边范围大于=右边)
小范围向大范围转 byte, short,char->int->long->float->double
强制转换(精度损失)
float f=(float)3.14;
4.2 引用数据类型
数组
多个相同类型数据集合
元素可以是任何数据类型,包括基本类型和引用类型
JAVA中的数组是只能分配在堆上面(因为其是引用类型)
元素为引用数据类型时,每一个元素都需要实例化。
一维数组
int arr[]; // JAVA语言中声明数组时不能指定其长度
arr=new int[5]; // 默认初始化为5个0,引用类型则为null
a[0]=6; a[1]=9; a[2]=8; // 数组元素下标从0开始;长度为n的数组的合法下标取值范围为0~n-1
//
int arr[] = { 6, 9, 8};
二维数组
int arr[][];
arr=new int[2][3];
//
int arr[][]={{1,2,3},{1,2,3}};
// 数组的长度(元素个数)
arr.length

- 语句
条件语句
语句块中只有一句时可以省略{}
int x=1;
if(x==1){
}
if(x==1){
}else{
}
if(x==1){
}else if(x==2){
}
if(x==1){
}else if(x==2){
}else if(x==3){
}else{
}
switch(x){ // x只能为int型
case 1:{
}
break; // 必须加,否则会穿透,继续执行case 2
case 2:{
}
case 3:{
}
break;
default:{
}
}
循环语句
for(int x=0;x<10;x++){
}
int x=10;
while(x>0){
x--;
}
x=10;
do{
x--;
}while(x>0);
continue; // 跳出本次循环
break; // 跳出循环
- 方法
// 调用实例方法(实参)
this.method(3);
// 修饰符 返回值类型 方法名(形参)
public int method(int x){
System.out.println("hello");
return x+1; // 返回值
}
递归
在一个方法内部对自身的调用就称为递归
public int method(int x){
if(x<0){ // 必须有临界值,否则死循环
return 10;
}
return method(x--);
}
- 程序执行过程

- 面向对象
JAVA语言基于C语言
C语言面向过程
将所有功能封装成各个方法
JAVA语言面向对象
世间万物都是类,类拥有属性和方法
拥有封装、继承、多态等特性
可重用性、可复用性
类和对象
类是用于描述同一类的对象的一个抽象,类可以看成一类对象的模板,对象可以看成该类的一个具体实例。
类之间的关系
关联关系(最弱的一种关系)
继承关系(教师继承人)
聚合关系(球队有队长和队员)
实现关系
public class Person{
String name;
public void run(){
}
}
- 处理异常
异常是指程序运行时出现的错误
除0溢出、数组下标越界、读取的文件不存在
程序运行过程中出现错误后生成异常类交给运行时系统,这个过程称之为抛出异常。运行时系统收到异常类后交给处理异常的代码段,这一过程称之为捕获异常。

自定义异常
throw new MyException("负值不合理", 1);
try {
} catch (MyException e) {
e.printStackTrace();
}
public class MyException extends Exception {
private int id;
/**
* 自定义异常类的构造方法
* @param message
* @param id
*/
public MyException(String message,int id) {
super(message);//调用父类Exception的构造方法
this.id = id;
}
/**
* 获取异常的代码
* @return
*/
public int getId() {
return id;
}
}
系统自带异常类型
try{
// 可能异常的代码块
System.out.println(arr[2]/0);
}catch(ArithmeticException e){
e.printStackTrace();
}
try{
System.out.println(arr[2]/0);
}catch(ArithmeticException e){ // 小范围异常在大范围异常前面,否则永远不会执行
e.printStackTrace();
}catch(HelloException e){
e.printStackTrace();
}finally{ // 一定会执行
}
public void method() throws HelloException{ // 将异常交由调用该方法的地方
throw new HelloException("error :"); // 抛出异常
}
10.GUI编程
不做了解
记得当时做过一个坦克大战游戏。哈哈
- 网络
可参考JAVAWeb之网络篇
一般的网络编程称为Socket编程
端口号
端口号是用来区分一台计算机上不同的应用程序
端口号在计算机内部是占2个字节。一台机器上最多有65536个端口号。
一个应用程序可以占用多个端口号。
端口号如果被一个应用程序占用了,那么其他的应用程序就无法再使用这个端口号了。
我们编写的程序要占用端口号的话占用1024以上的端口号,1024以下的端口号不要去占用,因为系统有可能会随时征用。
客户端通过端口1向服务器端请求连接,服务器端接受该客户端的连接请求以后,就在服务器端上安装一个Socket,然后让这个Socket与客户端的Socket连接,这样服务器端就可以与客户端互相通信了。
例
服务端Socket
import java.net.*;
import java.io.*;
public class TestServerSocket{
public static void main(String args[]) throws Exception{
// 指定端口号来监听客户端的连接
ServerSocket ss = new ServerSocket(6666);
/*服务器端接收客户端连接的请求是不间断地接收的,所以服务器端的
编程一般都是死循环,永不休止地运行着。*/
while(true){
Socket s = ss.accept();
/*在服务器端调用accept()方法接受客户端的连接对象,accept()方法是
一个阻塞式方法,一直在傻傻地等待着是否有客户端申请连接上来
然后服务器端的Socket插座就和客户端的Socket插座建立了连接了*/
/*客户端能否连接上服务器端,取决于服务器端是否接受客户端的连接请求
如果接受了客户端的连接请求,那么在服务器端就安装上一个Socket插座
通过这个插座与连接上的客户端就可以建立连接,互相通信了*/
System.out.println("A Client Connected!");
/*使用InputStream流接收从客户端发送过来的信息,使用DataInputStream数据流处理接收到的信息*/
DataInputStream dis = new DataInputStream(s.getInputStream());
/*使用readUTF(方法将接收到的信息全部读取出来,存储到变量str里面
readUTF()方法也是一个阻塞式方法,会傻傻地等待客户端发送信息过来,然后将接收到的信息读取出来
如果客户端不写东西过来,它就一直在服务器端傻傻地等待着,直到客户端写东西过来为止
堵塞式的方法效率往往是不高的,比如说一个客户端连接上来了,但是它迟迟不发送信息,
那么服务器端的程序就阻塞住了,这样另外一个客户端就连接不上来了,因为另外一个客户端要想连接
上服务器端,就必须得在服务器端调用accept()方法,可accept()方法必须得在下一次循环时才能够被
调用,现在服务器端的程序运行到调用readUTF()这个方法时就阻塞住了,它要等待着已经连接上来的
那个客户端发送信息过来后将信息读取出来,如果客户端一直不发信息到服务器端,那么readUTF()方法
就一直无法读取到信息,那么服务器端的程序会阻塞在这里,无法进行下次循环,这样其他的客户端就
无法连接到服务器端了*/
String str = dis.readUTF();
System.out.println(str);
}
}
}
客户端Socket
import java.net.*;
import java.io.*;
public class TestClientSocket{
public static void main(String args[]) throws Exception{
Socket s = new Socket("127.0.0.1",6666);
/*Client申请连接到Server端上*/
/*连接上服务器端以后,就可以向服务器端输出信息和接收从服务器端返回的信息
输出信息和接收返回信息都要使用流式的输入输出原理进行信息的处理*/
/*这里是使用输出流OutputStream向服务器端输出信息*/
OutputStream os = s.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
Thread.sleep(30000);/*客户端睡眠30秒后再向服务器端发送信息*/
dos.writeUTF("Hello Server!");
}
}
3. 中级基础
- 线程
创建主线程
VM虚拟机启动后public static void main()方法,会自动创建主线程
创建新线程
方式一:继承java.lang.Thread
run方法为线程体。调用start方法启动线程。
CustomThread.java
package com.sst.cx;
public class CustomThread extends Thread {
// 重写run方法
public void run(){
System.out.println("run");
}
}
Main.java
package com.sst.cx;
public class Main {
public static void main(String args[]){
// 开辟新线程(宏观并行)
CustomThread threadT = new CustomThread();
threadT.start(); // 调用start()方法启动新开辟的线程
System.out.println("main");
}
}
方式二:实现Runnable
CustomRunner.java
package com.sst.cx;
public class CustomRunner implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("thread");
}
}
Main.java
package com.sst.cx;
public class Main {
public static void main(String args[]){
// 开辟新线程
CustomRunner runner=new CustomRunner();
// 方式1.宏观并行
// Thread thread=new Thread(runner);
// thread.start();
// 方式2.同步(阻塞直到子线程结束)
runner.run();
System.out.println("main");
}
}
线程相关知识
// 开辟新线程
CustomRunner runner=new CustomRunner();
// 方式1.宏观并行
Thread thread=new Thread(runner);
thread.start();
// 获取 线程是否还活着
boolean isAlive=thread.isAlive();
// 获取线程优先级
int property=thread.getPriority();
// 睡眠线程1s
try {
thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// 睡眠当前线程3000ms(3s)
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 阻塞当前线程直到thread线程执行结束
try {
thread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 将线程放入就绪对列
thread.yield();
// 将线程放入wait对列
try {
thread.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 唤醒线程(从wait队列中唤醒)
thread.notify();
// 唤醒所有线程(wait队列中)
thread.notifyAll();
// 方式2.同步(阻塞直到子线程结束)
runner.run();
线程优先级(1~10,默认:5,越大越高)
java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程。线程调度器按照线程的优先级来决定调度哪个线程
// 设置优先级
thread.setPriority(6);
// 1
Thread.MIN_PRIORITY
// 10
Thread.MAX_PRIORITY
// 5
Thread.NORM_PRIORITY
线程安全
同步互斥锁(避免多线程同时访问)
synchronized (this) {
}
线程死锁
线程A锁住1想执行2,同时线程B锁住2想执行1
A
synchronized (1) {
synchronized (2) {
}
}
B
synchronized (2) {
synchronized (1) {
}
}
避免死锁:
不要同时锁住2个对象
生产者消费者问题
- 常用关键字
static关键字
在类中,使用static修饰的成员变量为静态成员变量(存放在数据区),由该类公用,仅在第一次使用时被初始化。使用static修饰的方法为静态方法,不能直接访问非静态变量和实例方法,可以先创建实例再去访问实例变量和实例方法。
private static int numOfLegs = 0;
super关键字
使用super来引用从父类继承的部分
this关键字
表示:调用当前方法的实例
使用this来引用当前对象的部分
可以使用this来区分成员变量和局部变量
abstract关键字
修饰类表示抽象类,不能被实例化
修饰方法表示抽象方法
abstract class Person{
private String name;
public abstract void run();
}
class Student extends Person{
public void run(){
}
}
Java语言规定,当一个类里面有抽象方法的时候,这个类必须被声明为抽象类。
equals方法(Object类的方法)
对象
Cat c1 = new Cat(1, 1, 1);
Cat c2 = new Cat(1, 1, 1);
c1==c2 // false(所引用的地址不一样)
boolean isEqual=c1.equals(c2); // false(所引用的地址不一样)
// 可通过覆写equals来实现比较
public boolean equals(Object obj){
if (obj==null){
return false;
}else{
// 判断一个对象是否属于某个指定类的实例
if (obj instanceof Cat){
Cat c = (Cat)obj;
if (c.color==this.color && c.weight==this.weight && c.height==this.height){
return true;
}
}
}
return false;
}
字符串
String s1 = new String("hello");
String s2 = new String("hello");
s1==s2 // false(所引用的地址不一样)
s1.equals(s2) // true,String类覆写了Object中的equals方法
Object类
所有java类的基类
// 默认继承Object,等效于 public class Person extends Object{}
public class Person{}
toString方法(Object方法)
//
System.out.println("person="+person); // 自动将person的toString方法,可以覆写toString方法
// 覆写
public String toString() {
return "hello";
}
一个".java"源文件中可以包括多个类,但只能有一个public类且类名必须与文件名相同。
类
// 声明 类
class Person{
// 属性
private int age;
public setAge(int age){
this.age=age;
}
public getAge(){
return this.age;
}
// 实例方法
public void run(){
}
// 构造函数与类名相同且没有返回值
// 默认的构造方法
Person(){
}
Person(int age){
this.age=age;
}
}
// 创建对象
Person person=new Person();
Person person=new Person(100);
String name=person.name;
person.run();
成员变量在类里面声明时如果不进行初始化,那么JAVA会默认给它初始化,而局部变量JAVA不会默认给它初始化
多态
动态绑定:变量在运行期间确定类型,类型确定后相应的方法和属性也确定了。
父类指针指向子类实例(不能调用子类新增的方法或属性)(向上转型)
Student、Teacher都继承自Person,并覆写run方法
Person person=new Student();
Person person=new Teacher();
person.run();
method(Person person){person.run();}
method(new Student());
子类指针指向父类实例(向下转型)
Student student=(Student)person;
重载
同一个类中,方法名相同参数不同(个数或类型)。返回类型不同不够成重构。构造方法也可以重构。
哈希编码表
JAVA虚拟机有一张哈希编码表,创建一个对象后会有一个独一无二的哈希编码用来查找对象。
接口 是一种特殊的抽象类。抽象方法和常量值的集合,没有变量和方法实现。
public interface Runner{
public static final id=100;
String name=@""; // 默认且只能为public static final
public void run(); // 默认abstrac 只能为public
}
Java只支持单继承,通过接口实现“多继承”
一个类可以实现多个接口
- 流
待摘录