一、java基础知识及基础语法
1、人机交互方式:
a) 图形化界面:GUI ,Graphical User Interface
b) 命令行方式:CLI ,Command Line Interface
2、dos常用命令:
dir :列出当前目录下内容 md:创建目录,make dir
rd :删除目录,remove dir cd: 进入指定目录,change dir
cd.. :退回上一级目录 cd/ :退回根目录
del:删除文件(直接删除,没有回收站) exit:退出命令行
3、java跨平台:
含义:是指java 语言编写的程序,一次编译后,可以在多个系统平台上运行。
原理:java程序是通过java虚拟机在系统平台上运行的,只要系统中安装了相应的jvm,该系统就能运行java程序。Java程序编译后成为二进制的字节码(bytecode),这是虚拟机的指令,与平台无关,字节码具有统一格式,不依赖具体的硬件环境,所以只要安装了jre,就能执行这些代码。
4、JDK 、JRE的区别
JDK:Java Development Kit,java开发工具包,JDK是提供给 Java 开发人员使用的,其中包含了 java 的开发工具,也包括了JRE。所以安装了JDK,就不用在单独安装JRE了。
JRE:Java Runtime Environment,java运行坏境。包括Java虚拟机(JVM:Java Virtual Machine)和 Java 程序所需的核心类库等,如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。
简单说就是JDK开发完的java程序,交给JRE去执行。
5、path、classpath的作用及配置方法
Path环境变量时告诉操作系统到哪里去查找JDK工具,而classPath则是告诉JDK工具在哪里去查找类文(.class)。JDK默认情况下回哎当前工作目录下(变量值用“.”表示)以及JDK的lib目录下寻找所需要的class文件,因此java程序放在这两个文件夹下,不设置classpath变量执行环境也可以找得到,但其他文件夹就不行。
Path配置:1)我的电脑--属性--高级系统设置--环境变量。2)编辑 path 环境变量,在变量值开始处加上 java 工具所在目录(JDK 安装根目录的 bin 目录),后面用 “ ; ”和其他值分隔开即可。3)打开DOS命令行,任意目录下敲入javac。如果出现javac 的参数信息,配置成功。
ClassPath配置:同path配置方法相同,不过变量值应该为class文件的目录地址。
6、Hello World程序初探:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
1) 储存文件时,源文件扩展名必须是java,且源文件名必须和程序中申明的为public class的类的名字完全一致,包括大小写。一个源文件最多只能有一个类可以被定义成public的,若不包含public类,则源文件的保存名字可任意。
2) 程序中可以有若干个类,每个类可以有若干个方法,但是其中必须有一个类中包含一个且只能有一个public static void main(String [] args)方法,main方法是所有java应用程序的入口点。
3) 编译:javac HelloWorld.java,若无错误,会在当前目录生成class字节码文件。
4) 运行:java HelloWorld。
5) 整个流程:编写代码(.java文件) -- 编译(javac.exe)生成(类名.class)文件 -- 运行(java.exe,JVM会先加载,运行的是类名) -- 得出运行结果。
6) Java是对大小写敏感的,也就是说是区分大小写的,不能混用。
7) main方法的作用:程序的入口,保证程序的独立运行(因为只能有一个static void main),被JVM调用。
7、注释:
Java中的注释类型:
单行注释://注释文字
多行注释:/* 注释文字 */,
文档注释:(java 特有)/**注释文字*/,注释内容可以被JDK工具javadoc解析,生 成一条文件形式的程序说明文档。
注意:被注释的文字,不会被JVM(java虚拟机)解释执行。多行注释和文档注释不允许有注释嵌套。
8、标示符与关键字
标示符意义:标明类名、变量名、方法名、数组名、文件名等程序中各元素的字符序列。
标示符命名规则:
1)由26个英文字母大小写,数字:0-9 ,_或 $ 组成,此处的字母 可以是中文、日文 。
2)数字不可以开头。
3)不可以使用关键字和保留字,但能包含关键字和保留字。
4)Java中严格区分大小写,长度无限制。
5)标识符不能包含空格。
命名规范:
a)包名:多单词组成时所有字母都小写:xxxyyyzzz,可以用.连接
b)类名接口名:多单词组成时,所有单词的首字母大写:XxxYyyZzz,别用java api 中的类名作为自己的类名。
c)变量名和函数名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写:xxxYyyZzz
d)常量名:所有字母都大写。多单词时每个单词用下划线连接:XXX_YYY_ZZZ
关键字:被Java语言赋予了特殊含义,用做专门用途的字符串(单词),关键字中所有 字母都为小写。主要有以下5类。
类类型:(Class Type) package,class,abstract,interface,implements,native, this,super,extends,new,import,instanceof,public,private,protected
数据类型:(Data Type) char,double,enum,float,int,long,short,boolean, void,byte,true,false,null
控制类型(Control Type) break,case,continue,default,do,else,for,goto, if,return,switch,while,throw,throws,try,catch,synchronized, final,finally,transient,strictfp。
存储类型:(Storage Type) register,static
其他类型:(Other Type) const,volatile
注意:1、关键字都是小写。2、无sizeof运算符,因为数据类型长度和表示是固定的。 3、goto和const虽然从未使用,但是也作为java关键字保留下来。
9、常量和变量
常量:常量表示不能改变的数值。定义:final dataType CONST_NAME = VALUE;
变量:内存中的一个存储区域,该区域有自己的名称(变量名)和类型(数据类型), 每个变量必须先声明,后使用;该区域的数据可以在同一类型范围内不断变化。
定义变量的格式: 数据类型 变量名 = 初始化值。变量的作用域:一对{ }之间有效。
成员变量和局部变量:局部变量不是直接定义在类体中的,比如说定义在方法中,局部 变量使用前必须初始化,作用域从定义处到代码块结束;成员变量,定义在类 中,而不是方法中,又称为字段Field或者全局变量,作用于整个类中。成员变量会在类创建时默认初始化,局部变量不会。
变量类型:基本数据类型——布尔型,字符型,数值型(整数、浮点),存放在栈中
引用数据类型——接口,数组,类(字符串是类),存放在堆中,栈放地址
整数类型:整型常量默认为 int 型,声明 long 型常量须后加 ‘l’ 或 ‘L’。
浮点类型:浮点型常量默认为 double 型,声明 float 型常量,须后加 ‘f’ 或 ‘F’。 十进制数形式:如:5.12 ;512.0f ;.512 (必须有小数点)
科学计数法形式:如:5.12e2 ; 512E2 ; 100E-2
字符类型:char 型数据用来表示通常意义上"字符"。字符型有三种表现形式,
char c1 = 'a' ; char c3 = '\n' ; char c2 = ‘\uXXXX’;
XXXX代表一个十六进制整数,char 类型是可以进行运算的。
布尔型: boolean类型数据只允许取值true和false。
类型装换:
自动类型转换(隐式):容量小的类型自动转换为容量大的数据类型。数据类型按容量大小排序为: 1)有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算。2)byte,short,char之间不会相互转换,他们三者在计算时首先转换为int类型。3)当把任何基本类型的值和字符串值进行连接运算时(+),基本类型的值将自动转化为字符串类型。
强制类型转换(显式):自动类型转换的逆过程,将容量大的数据类型转换为容量小的数据类型。使用时要加上强制转换符(()),但可能造成精度降低或溢出,格外要注意。通常,字符串不能直接转换为基本类型,但通过基本类型对应的包装类则可以实现把字符串转换成基本类型。如: String a = “43”; int i = Integer.parseInt(a);boolean类型不可以转换为其它的数据类型。
10、进制
对于整数,有四种表示方式:
二进制:0,1 ,满 2 进 1.以 0b 或 0B 开头。
十进制:0-9 ,满 10 进 1.
八进制:0-7 ,满 8 进1. 以数字 0 开头表示。
十六进制:0-9 及 A-F,满 16 进1. 以 0x 或 0X开头表示。此处的A-F不区分大小写。
所有数字在计算机底层都以二进制形式存在。计算机以补码的形式保存所有的整数。正数的补码与其原码相同;负数的补码是在其反码的末位加1。原码:直接将一个数值换成二进制数。反码:是对原码按位取反,只是最高位(符号位)保持不变。
进制转换功能函数:
/**
* 数字进制转换的原理(int): 数据以二进制在电脑中存储,有一下推论: (0B)1011 = 1*2^3 + 0*2^2 + 1*2^1 + 1*2^0
* = 8+2+1 = 11 = 0xB; 所以十进制的数字先转换成二进制(计算机自动完成),每4位就是它对应的一个16进制的位值。
* 则任务就变成了,如何获取4为数据,从第4位到高四位,依次采取,屏蔽高位,保留低位 0000 1111 0110 1010 & 0000 0000 0000
* 1111,则高位全部被屏蔽成0,低4位保留1010; 故 (int)a & 15 = 高四位被屏蔽,低四位保留的数字
*
* 8进制同理,不过八进制是3位数据依次处理
*
*/
public class ConveresionNumber {
// 10->16
public static void conversionToHex(int num) {
conversion(num, 15, 4);
}
// 10->2
public static void conversionToBin(int num) {
conversion(num, 1, 1);
}
// 10->8
public static void conversionToB(int num) {
conversion(num, 7, 3);
}
// 采用查表法,参数依次为:需要转换的数字,权,移动的位数
private static void conversion(int num, int base, int offset) {
if (num == 0) // 错误检测
{
System.out.println(0);
return;
}
// 创建表格以供查找
char[] chs = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
'B', 'C', 'D', 'E', 'F' };
char[] arr = new char[32]; // int型数据的32位,每一位以字符形式打印出来
int pos = arr.length - 1;
while (num != 0) {
int temp = num & base; // 获取到num的offset位数据,存放在temp中(低位中)
arr[pos--] = chs[temp];// 查表获取temp对应的数字字符
// >>> 被移位二进制最高位无论是0或者是1,空缺位都用0补。
num = num >>> offset;
}
// 一次输出chs,即为num的各位的数据
for (int i = pos + 1; i < arr.length; i++) {
System.out.print(arr[i]);
}
System.out.println();
}
// 测试
public static void main(String[] args) {
conversionToHex(15); //F
conversionToBin(3); //11
conversionToB(8); //10
}
}
11、运算符与表达式
算术.算符(+ 、— 、* 、/ 、%)
赋值运算符(= 、+=、-=、*=、/=,、%=)
关系运算符(>、>=、<、<=、!=)
条件运算符(&&、||、!&、|、^)
位运算符(&、|、^、~、>>、<<、<<<、>>>)
1)如果对负数取模,可以把模数负号忽略不记,如:5%-2=1。 但被模数是负数就另当别论。
2)对于除号“/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。
3)“+”除字符串相加功能外,还能把非字符串转换成 字符串.例如:System.out.println("5+5="+5+5) :结果5+5=55
4)instanceof是运算符,检查是否是类的对象
5)逻辑运算符用于连接布尔型表达式,在Java中不可以写成3<x<6,应该写成x>3 && x<6
6)“&”和“&&”(短路与)的区别:单&时,左边无论真假,右边都进行运算;双&时,如果左边为真,右边参与运算,如果左边为假,那么右边不参与运算。或、短路或同理
7)位运算符:a)<< 被移除的高位丢弃,空缺位补0;b)>> 被移位的二进制最高位是0,右移后,空缺位补0,最高位是1,空缺位补1;c)>>> 被移位二进制最高位无论是0或者是1,空缺位都用0补。
8)三元运算符:(条件表达式)?表达式1:表达式2;如果条件为true,运算后的结果是表达式1;如果条件为false,运算后的结果是表达式2
public class Demo2 {
public static void main(String[] args) {
String s = "lz";
s = (s == "lz" ? "正确" : "错误");
System.out.println(s);
}
}
结果:正确
12、程序流程控制
1)选择结构:if-else 语句;switch 语句。switch(表达式)中表达式的返回值必须是下述几种类型之一:int, byte, char, short, 枚举, 字符串(java7);case子句中的值必须是常量,且所有case子句中的值应是不同的;default子句是任选的;break语句用来在执行完一个case分支后使程序跳出switch语句块;
2)循环结构:for 循环;while 循环;do/while 循环(至少能执行一次)
3)流程控制语句:break,终止(跳出)该循环,continue,跳过本次循环;break语句出现在多层嵌套的语句块中时,可以通过标签指明要终止的是哪一层语句块 :
label1: { ……
label2: { ……
label3: { ……
break label2;
……
}
}
}
break只能用于switch语句和循环语句中。continue 只能用于循环语句中。标号语句必须紧接在循环的头部。标号语句不能用在非循环语句的前面。break和continue之后不能有其他的语句,因为程序永远不会执行break 和 continue之后的语句。
Java7新增switch中的判断句可以使用字符串,实例如下:
//switch 可以用字符串作为判断表达式
public class test {
public static void main(String[] args) {
String s = "hehe";
switch(s){
case "a":
System.out.println(1);
break;
case "hehe":
System.out.println(2);
break;
}
}
}
输出:2
13、数组
数组是多个相同类型数据的组合,实现对这些数据的统一管理;数组属引用类型,数组型数据是对象(Object),数组中的每个元素相当于该对象的成员变量;数组中的元素可以是任何数据类型,包括基本类型和引用类型。
1)一维数组的声明方式: type var[] 或 type[] var;Java语言中声明数组时不能指定其长度(数组中元素的数), 例如: int a[5]; //非法;数组值存放在堆内存中,栈中存放堆内存首地址。Java中使用关键字 new 创建数组对象;定义并用运算符 new 为之分配空间后,才可以引用数组中的每个元素;数组元素下标从0开始;数组是引用类型,它的元素相当于类的成员变量,因此数组一经分配空间,其中的每个元素也被按照成员变量同样的方式被隐式初始化。
2)数组的静态初始化与动态初始化:静态初始化:在定义数组的同时就为数组元素分配空间并赋值,如int a[] = { 3, 9, 8};动态初始化:数组定义与为数组元素分配空间并赋值的操作分开进行,如a = new int[3];a[0] = 3;a[1] = 9;a[2] = 8;
3)多维数组:Java中多维数组被做为数组的数组处理;Java中多维数组的声明和初始化应按从高维到低维的顺序进行,如int t [][] = new int [4][];//t有4行,第一个维数不空即可。Java中多维数组不必须是规则矩阵形式,即t[0].length可以不等于t[1].length。
4)内存分析:栈内存,存储局部变量,数据使用完,自动释放空间。堆内存,数组和对象,通过new创建的实例都存放在堆内存中,但是变量名会对应一个栈内存,栈中存放此堆内存的地址
数组应用:二分法查找、四种排序方法:冒泡、快速、插入、选择
//二分法查找(假设数据以升序排列),以int为例
public class BinarySearch {
public static int binarySearch(int [] array,int key){
if(array.length == 0){
return -1;
}
int first = 0;//开始位置
int last = array.length-1;//结束位置
int mid;//中间位置
while(first<=last){//查找时必须开始<结束
mid = (first+last)/2;//中间位置 = (开始+结束)/2
if(array[mid]==key){// 找到,返回数组下标索引
return mid;
}else if(array[mid]>key){ //中间值大于key,重设结束位置为当前中间值
last = mid;
}else{ //中间值小于key,重设开始位置为当前中间值
first = mid;
}
}
return -1; // 没在while中找到
}
}
/**
* 冒泡排序:
* 最经典的排序方法,利用两个for循环语句,遍历比对相邻元素大小
*
*/
public class BubbleSort {
public static void bubbleSort(int [] array){
// i:总共需要排序的趟数,也就是已经排好的元素个数
for(int i=0;i<array.length;i++){
// j:从0开始,array[j]当前比较的元素,也就是冒泡移动的元素
for(int j=0;j<array.length-i-1;j++){
if(array[j]>array[j+1]){
int temp = array[j+1];
array[j+1] = array[j];
array[j] = temp;
}
}
}
}
//测试
public static void main(String[] args) {
int [] array = {5,2,7,3,10,6,8,9,5,4};
System.out.println("排序前:");
for(int a:array){
System.out.print(a+" ");
}
System.out.println();
//对最后一个元素插入排序,则会递归到所以元素
bubbleSort(array);
System.out.println("排序后:");
for(int a:array){
System.out.print(a+" ");
}
}
}
/**
* 插入排序原理:
* 假设元素i之前的[0,i-1]元素已经排列好,则将i依次与i-1、i-2……向前比较换位,直到找到合适的位置
* 优点是能利用之前排序的到序列。
*
*/
public class InsertionSort {
//递归实现,因为整个过程是一个递归的,每一次都重复同样的操作
//传入本次插入排序的元素角标,假设之前元素以排好
public static void insertionSort(int [] array,int index){
if(index>0){
insertionSort(array,index-1);
for(int i=0;i<index;i++){
if(array[i]>array[index]){
//交换两个数据
int temp = array[index];
array[index] = array[i];
array[i] = temp;
}
}
}else{
return;
}
}
//测试
public static void main(String[] args) {
int [] array = {5,2,7,3,10,6,8,9,5,4};
System.out.println("排序前:");
for(int a:array){
System.out.print(a+" ");
}
System.out.println();
//对最后一个元素插入排序,则会递归到所以元素
insertionSort(array,array.length-1);
System.out.println("排序后:");
for(int a:array){
System.out.print(a+" ");
}
}
}
/**
* 快速排序。 以上排序方法效率并不高,于是我通过学习理解实现快速算法如下(以int数组为例)。
* 算法小结:核心两步
* step1. 将一个数组按照一个基数分成左右两部分,左边组小于基数,右边组大于基数
* step2. 递归调用step1的方法进行循环多次分组,直到最后实现了最终排序。
*/
public class QuickSort {
//产生随机数组用于测试排序
public static int[] getArray(int length){
int [] array = new int[length];
Random random = new Random();
for(int i=0;i<length;i++){
array[i] = random.nextInt(100);
}
return array;
}
//1.重组一个数组,指定左端与右端,以及重组成左右的重组依据(即指订排列基数),返回中间值的位置
//采用数组末尾元素为排列依据。效果:原数组(1,5,4,3,8,9,6) --> 1,5,4,3, 6 ,8,9
public static int baseStep(int[] array,int left,int right,int point){
//获取最左端和最右端开始位置,以及排列的基数,注意右端从array.length-2开始,数组尾数作为基数。
int leftPtr = left-1;
int rightPtr = right;
int pointNum = point;
//循环执行,直到左右分成两组,基数居中,左小右大
while(true){
//leftPtr定位到左端大于基数的数,rightPtr定位到右端大于基数的数
while(leftPtr<rightPtr && array[++leftPtr]<pointNum);
while(rightPtr>leftPtr && array[--rightPtr]>pointNum);
//交换左右两端Ptr定位到的数字
int temp = array[leftPtr];
array[leftPtr] = array[rightPtr];
array[rightPtr] = temp;
//分组完成,跳出循环
if(leftPtr>=rightPtr){
break;
}
}
//此时将基础插入到左右两组的中间,即此时的leftPtr与基数互换
int temp = array[leftPtr];
array[leftPtr] = array[right];
array[right] = temp;
//返回此时位于左右两组数中间的基数的位置指针leftPtr
return leftPtr;
}
//2. 递归调用baseStep完成所有排列
public static void sort(int [] array ,int left,int right){
//设置递归退出口
if( left >= right ){
return;
}else{
//每次分组的基数为sort方法的参数array的最后一个元素,角标为right
int point = array[right];
//获取每次分组后中间基数的位置
int mid = baseStep(array, left, right, point);
//分别开始重新对左边组,和右边组再进行大小分组成两部分(基数居中)
sort(array, left, mid-1);
sort(array,mid+1,right);
}
}
public static void main(String[] args) {
int[] array = new int[20];
array = QuickSort.getArray(20);
//打印原数组
for(int a:array){
System.out.print(a + " ");
}
//进行快速排序
sort(array, 0, array.length-1);
//输出排序过后的数组
System.out.println();
for(int a:array){
System.out.print(a + " ");
}
}
}
/**
* 选择排序原理:
* 遍历数组,设当前需要排列的元素序号是i,则在[i+1,length-1](即之后的子数组)中找到最小/大值,
* 与元素i互换,这样遍历所有元素则实现排序。
*
*/
public class SelectionSort {
public static void selectionSort(int [] array){
for(int i=0;i<array.length-1;i++){ //遍历每一个数组元素,最后一个元素不用遍历
//从当前遍历的元素后面找到最小值
int min = array[i+1];
//记录后面元素最小值的下标,这两句可以简化成一句,只记录下标即可
int min_num = i+1;
for(int j=i+1;j<array.length;j++){
if(array[j]<min){
min = array[j];
min_num = j;
}
}
if(min<array[i]){
int temp = array[i];
array[i] = min;
array[min_num] = temp;
}
}
}
//测试
public static void main(String[] args) {
int [] array = {5,2,7,3,10,6,8,9,5,4};
System.out.println("排序前:");
for(int a:array){
System.out.print(a+" ");
}
System.out.println();
selectionSort(array);
System.out.println("排序后:");
for(int a:array){
System.out.print(a+" ");
}
}
}
6)arrays工具类的使用:arrays工具的使用可以简化对数组的操作。提高效率,具体查看api文档
7)增强型for循环,for-each的使用: for(类型 变量名:数组名){ 代码块 }