一.关于Java
高级计算机语言,可编写跨平台应用软件、完全面向对象的程序设计语言。
技术平台:Java SE(桌面应用)、Java EE(web应用、平台企业版)、Java ME(手机应用,平台微型版)
特点:简单易用、安全可靠、跨平台、面向对象、支持多线程、自动垃圾回收(c语言没有)
对于jvm相关知识点,我有专门的去说这里不做强调【jvm理解】
JDK:
- bin目录:所有可执行程序[Javac.exe(Java编译器)、Java.exe(Java运行工具)、jar.exe(打包工具)、Javadoc.exe(文档生成工具)]都存放在bin目录;
Java编译器:可以将编写好的Java文件编译成Java字节码文件,即将.java文件编译成.class文件,供java虚拟机进行读取、执行;
Java运行工具:会启动一个Java虚拟机进程,专门负责运行由Java编译器生成的字节码文件)
- db目录:小型数据库,引入了开源数据库——JavaDB;
- jre目录:Java运行时环境的根目录,包含Java虚拟机、运行时类包、Java应用启动器以及bin目录,但不包含开发环境中的开发工具,jre只负责编写,不负责编译(只有java无javac);
- lib目录:Java类库或库文件,开发工具使用的归档包文件;
- src文件夹:放置JDK核心类的源代码。
PATCH环境变量:配置存储Java的编译和运行工具所在路径
既然是基础篇,那就必须谈谈Java特性
封装:隐藏对象的属性和实现,仅对外提供访问方式(特点:①变化隔离、②使用便利、③高重用性、④高安全性)。
继承:关键字extends,从已有类中派生出新的类,吸收了已有类的数据属性跟行为,并能扩展(特点:①高重用性、②维护简单)[注:Java中不支持多继承,但支持多重继承]。
扩展:这里说到继承,那就有必要说说“实现”!
关键字implements,类是单一继承,但是可多实现接口,通过逗号隔开,可以变相获得多继承的特性。其中可使用super关键字实现对父类成员的访问,使用this关键字指向自身引用。
至此插播一条新问题!!!
重写与重载的区别?
重写:父类对子类允许访问的方法的实现过程进行重新编排,出入参都不能改变。“即外壳不变,核心改变”。
重载:同一个类中,方法名相同,参数不同,返回值可同可不同。
多态:这个需要多了解了解,多态是同一个行为具有多个不同的表现形式或形态的能力。即就是同一个接口,使用不同的实例而执行不同的操作。简而言之,同种属性或者方法被不同实例继承后,可进行更好的扩展(方法的重写和重载也是多态的一种表现“同种事务,多种形态”)。
优势:①降低耦合、②扩展性高、③灵活性高、④简化性高public class Test { public static void main(String[] args) { show(new Cat()); // 以 Cat 对象调用 show 方法 show(new Dog()); // 以 Dog 对象调用 show 方法 Animal a = new Cat(); // 向上转型 a.eat(); // 调用的是 Cat 的 eat Cat c = (Cat)a; // 向下转型 c.work(); // 调用的是 Cat 的 work } public static void show(Animal a) { a.eat(); // 类型判断 if (a instanceof Cat) { // 猫做的事情 Cat c = (Cat)a; c.work(); } else if (a instanceof Dog) { // 狗做的事情 Dog c = (Dog)a; c.work(); } } } abstract class Animal { abstract void eat(); } class Cat extends Animal { public void eat() { System.out.println("吃鱼"); } public void work() { System.out.println("抓老鼠"); } } class Dog extends Animal { public void eat() { System.out.println("吃骨头"); } public void work() { System.out.println("看家"); } }
二.数据类型
转换规则:
从存储范围小的类型到存储范围大的类型。简言之,由低到高。
具体规则为:byte→short(char)→int→long→float→double
扩展:经典面试题
基本数据类型与引用数据类型的区别
扩展:引用数据类型非常多,类、接口、数组、枚举、注解、字符串等都属于引用类型,简而言之,所有非基本数据类型都是属于引用数据类型。
①存储位置:
基本数据类型在方法中定义的非全局基本数据类型变量的内容都存储在栈中。
引用数据类型的内容存储在堆中,栈中存放的是内容的内存地址。
pulbic class TestClass{
public static void main(String[] args){
//基本数据类型
int i = 1;
double d = 1.2;
//引用数据类型
String str = "123";
}
}
②传递方式:
基本数据类型在方法中定义的非全局基本数据类型变量调用方法时,作为参数是按数值传递。
//基本数据类型作为方法参数被调用
pulbic class TestClass{
public static void main(String[] args){
int a = 1;
System.out.println("调用方法前a的值:"+ a)
test(a);
System.out.println("调用方法后a的值:"+ a)
}
public static void test(int temp){
temp = 0;
}
}
引用数据类型的变量调用方法时,作为参数传递的是引用的副本,调用时在栈中开辟新空间,并指向book具体内容,方法执行完成后在栈中的内容会释放掉。
//引用数据类型作为方法参数被调用
class Book{
String name;
double price;
public Book(String name,double price){
this.name = name;
this.price = price;
}
public void getInfo(){
System.out.println("图书名称:"+ name + ",价格:" + price);
}
public void setPrice(double price){
this.price = price;
}
}
public class Main{
public static void main(String[] args){
Book book = new Book("123",1.1);
book.getInfo();
test(book);
book.getInfo();
}
public static void test(Book temp){
temp.setPrice(2.2);
}
}
三.运算符
运算符:在计算机中,对常量或变量进行操作的符号。
算数运算符
赋值运算符
关系运算符
逻辑运算符
位运算符
三元运算符
语法格式:关系表达式 ? 表达式1 : 表达式2;
解:问号前面的位置是判断的条件,判断结果为boolean型,为true时调用表达式1,为false时调用表达式2。其逻辑为:如果条件表达式成立或者满足则执行表达式1,否则执行表达式2。
四.集合
五.异常
Thorwable:属于类,是所有异常和错误的超类。
Exception:程序运行过程中出现的不正常状态,是发生在运行期间,影响正常工作的情况。
Error:错误不是异常,不可控,肯定会导致程序非正常终止。
异常分两大类:
运行异常:如果空指针、下标越界,这种可以通过捕获进行处理,也可不处理,属程序逻辑错误,编译时不会去检测。
编译异常:除RuntimeException以外的异常,最直观的就是编译时会检测,不进行处理会编译不通过。
至此,谈下扩展“异常处理机制”!
- try:定义可能发生异常区域;
- catch:捕获try中异常(可多层捕获,但依据规则范围是先小后大);
- finally:必须执行,即无论是否存在异常都会执行块,处理善后工作;
- throw:抛出异常;
- throws:声明异常。
六.算法
二分查找:折半查找,要求查找的数组或列表有序,即每次取中间值与最终值比较,小则+1,大则-1。
/**
* 二分查找
* @param srcArray 源数组
* @param des 目标元素
* @return 如果找到则返回索引位置,找不到则返回-1
*/
public static int binarySearch(int[] srcArray, int des) {
//定义初始最小、最大索引
int start = 0;
int end = srcArray.length - 1;
//确保不会出现重复查找,越界
while (start <= end) {
//计算出中间索引值 >>> 逻辑右移(位运算符,上文有提到) 也就是 int middle = (end + start)/2
int middle = (end + start)>>>1 ;//防止溢出
if (des == srcArray[middle]) {
return middle;
//判断下限
} else if (des < srcArray[middle]) {
end = middle - 1;
//判断上限
} else {
start = middle + 1;
}
}
//若没有,则返回-1
return -1;
}
冒泡排序:比较相邻两元素大小,若前者大于后者,则交换位置。
/**
* 冒泡排序
* @param arr 源数组
* @return 返回排序完成后的数组
*/
public static int[] bubbleSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
插入排序算法:构建有序序列,从后向前扫描,找到相应位置并插入。
/**
* 插入排序
* @param arr 源数组
* @return 返回排序完成后的数组
*/
public static int[] insertionSort(int arr[]) {
for (int i = 1; i < arr.length; i++) {
//插入的数
int insertVal = arr[i];
//被插入的位置(准备和前一个数比较)
int index = i - 1;
//如果插入的数比被插入的数小
while (index >= 0 && insertVal < arr[index]) {
//将把 arr[index] 向后移动
arr[index + 1] = arr[index];
//让 index 向前移动
index--;
}
//把插入的数放入合适位置
arr[index + 1] = insertVal;
}
return arr;
}
快速排序算法:通过一趟排序分成两个独立部分,一部分要比另一部分数据都要小,再按照此方法对两部分数据进行排序。
/**
* 快速排序
*
* @param arr 需要排序的数组
* @param start 数组的最小索引: 0
* @param end 数组的最大索引: arr.length - 1
* @return 排序好的数组
*/
public static int[] quickSort(int arr[], int start, int end) {
int pivot = arr[start];
int i = start;
int j = end;
while (i < j) {
while ((i < j) && (arr[j] > pivot)) {
j--;
}
while ((i < j) && (arr[i] < pivot)) {
i++;
}
if ((arr[i] == arr[j]) && (i < j)) {
i++;
} else {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
if (i - 1 > start) arr = quickSort(arr, start, i - 1);
if (j + 1 < end) arr = quickSort(arr, j + 1, end);
return (arr);
}
希尔排序算法:将整个待排序记录序列分割成若干子序列分别进行排序,待整个序列中记录“基本有序”时,再对全体记录进行依次直接插入排序。
/**
* 希尔排序
* @param a
*/
private static void shellSort(int[] a) {
int dk = a.length / 2;
while (dk >= 1) {
//类似插入排序,只是插入排序增量是 1,这里增量是 dk,把 1 换成 dk 就可以了
for (int i = dk; i < a.length; i++) {
if (a[i] < a[i - dk]) {
int j;
int x = a[i];//x 为待插入元素
a[i] = a[i - dk];
for (j = i - dk; j >= 0 && x < a[j]; j = j - dk) {
//通过循环,逐个后移一位找到要插入的位置。
a[j + dk] = a[j];
}
a[j + dk] = x;//插入
}
}
dk = dk / 2;
}
}
归并排序算法:将两个或多个有序表合并成一个新的有序表,先分成若干子序列,再进行合并。是比较有效且稳定的排序算法。
/**
* 归并排序
* @param nums 待排序数组
* @param l 开始索引:0
* @param h 最大索引:nums.length - 1
* @return 排序好的数组
*/
public static int[] mergeSort(int[] nums, int l, int h) {
if (l == h)
return new int[]{nums[l]};
int mid = l + (h - l) / 2;
int[] leftArr = mergeSort(nums, l, mid); //左有序数组
int[] rightArr = mergeSort(nums, mid + 1, h); //右有序数组
int[] newNum = new int[leftArr.length + rightArr.length]; //新有序数组
int m = 0, i = 0, j = 0;
while (i < leftArr.length && j < rightArr.length) {
newNum[m++] = leftArr[i] <= rightArr[j] ? leftArr[i++] : rightArr[j++];
}
while (i < leftArr.length)
newNum[m++] = leftArr[i++];
while (j < rightArr.length)
newNum[m++] = rightArr[j++];
return newNum;
}
桶排序算法:划分成多个大小相同子区间,再每个子区间进行排序。
/**
* 桶排序
*
* @param data 待排序数组
*/
public static void bucketSort(int data[]){
int n = data.length;
int bask[][] = new int[10][n];
int index[] = new int[10];
int max = Integer.MIN_VALUE;
for (int i = 0; i < n; i++) {
max = max > (Integer.toString(data[i]).length()) ? max : (Integer.toString(data[i]).length());
}
String str;
for (int i = max - 1; i >= 0; i--) {
for (int j = 0; j < n; j++) {
str = "";
if (Integer.toString(data[j]).length() < max) {
for (int k = 0; k < max - Integer.toString(data[j]).length(); k++)
str += "0";
}
str += Integer.toString(data[j]);
bask[str.charAt(i) - '0'][index[str.charAt(i) - '0']++] = data[j];
}
int pos = 0;
for (int j = 0; j < 10; j++) {
for (int k = 0; k < index[j]; k++) {
data[pos++] = bask[j][k];
}
}
for (int x = 0; x < 10; x++) index[x] = 0;
}
}
基数排序算法:将整数按位数切割成不同的数字,然后按每个位数分别比较。
/**
* 基数排序
* @param number 待排序的数组
* @param d 表示最大的数有多少位
*/
public static void sort(int[] number, int d) {
int k = 0;
int n = 1;
int m = 1; //控制键值排序依据在哪一位
int[][] temp = new int[10][number.length]; //数组的第一维表示可能的余数0-9
int[] order = new int[10]; //数组order[i]用来表示该位是i的数的个数
while (m <= d) {
for (int i = 0; i < number.length; i++) {
int lsd = ((number[i] / n) % 10);
temp[lsd][order[lsd]] = number[i];
order[lsd]++;
}
for (int i = 0; i < 10; i++) {
if (order[i] != 0)
for (int j = 0; j < order[i]; j++) {
number[k] = temp[i][j];
k++;
}
order[i] = 0;
}
n *= 10;
k = 0;
m++;
}
}
还有剪枝算法、回溯算法、最短路径算法、最大子数组算法、最长公共子序算法 、最小生成树算法能力有限,实属没懂!!!