1、.java程序编译:
javac xx.java //生成xx.class文件
java xx //如果包含了package,需要在package上一目录下执行
2、input
Scanner scanner = new Scanner(System.in);
if (scanner.hasnextInt()){ //判断输入的是否为INT类型
int a = scanner.nextInt();
}
scanner.close();//用完scanner后一定要关闭!
3、将.class文件拖入idea即可实现反编译。
4、static可以用来修饰类的成员方法、类的成员变量被static关键字修饰的方法或者变量不需要依赖于对象来进行访问。在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。
static用法
5、八大基本类型
byte1 short2 int4 long8
float4 double8
char1 bool1bit
Java方法
1、方法的重载:
- 方法名称必须相同。
- 参数列表必须不同(个数、类型、参数排列顺序)。
- 方法的返回类型可以相同也可以不相同。
- 仅仅返回类型不同不足以成为方法的重载。
2、可变参数
在方法声明中,在指定参数类型后加一个省略号(…),一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。
public class Demo03 {
public static void main(String[] args) {
Demo03 demo03 = new Demo03();
demo03.test(1,2,3);
}
public void test(int... i){
for (int i1 : i) {
System.out.println(i1);
}
}
}
3、递归
- 递归头:什么时候不调用自身方法,如果没有头,将陷入死循环。
- 递归体:什么时候需要调用自身方法。
Java数组
1、数组的创建:
dataType[] arrayRefVar; //首选
dataType arrayRefVar[];
//使用new创建数组
dataType[] arrayRefVar = new dataType[arraySize];
//静态初始化:创建+赋值
int[] a={1,2,3,4,5};
//动态初始化
int[] b = new int[10];
b[0]=10;
- 长度固定,一经创建,大小不可改变。
- 数组对象本身是在堆中
- 数组也是对象,数组元素相当于对象的成员变量
2、java内存分析:
(1)堆:存放new的对象和数组;可以被所有线程共享,不会存放别带对象引用
(2)栈:存放基本变量类型(包含这个基本类型的具体数值);引用对象的变量(会存放这个引用在堆里面的具体地址)
3、数组的使用:
// for-each
for (int num : nums) {
System.out.println(num);
}
4、Array类:
Arrays类中的方法都是static修饰的静态方法,在使用时可以直接通过类名进行调用,而不是使用对象来调用。(是不用而不是不能)
具有以下常用功能:
- 给数组赋值:fill
- 给数组排序:sort,升序
- 比较数组:equals
- 查找数组元素:binarySearch可以对排好序的数组进行二分查找
5、排序
冒泡排序(O(n^2))
(1)比较数组中相邻两个元素,如果第一个数比第二个数大,我们交换他们的位置
(2)每一次比较,都会产生出一个最大,或者最小的数字
(3)下一轮则可以减少一次排序
(4)依次循环,直到结束
for (int i = 0; i <a.length-1; i++) {
for (int j = 0; j <a.length-i-1; j++) {//每轮-1
if(a[j]>a[j+1]){
t = a[j];
a[j] = a[j+1];
a[j+1]=t;
}
}
}
选择排序(O(n^2))
(1)选择排序一共有数组大小-1轮排序
(2)每一轮排序又是一个循环,选出未排序数中最小数,交换到未排序数中第一个位置。
(3)第n次排序得到前n个有序数。
for (int i = 0; i < a.length-1; i++) {
mini = a[i];
pos = i;
for (int j = i+1; j <a.length ; j++) {
if (a[j]<mini){
mini=a[j];
pos = j;
}
}
if (pos!=i){
tmp = mini;
a[pos] = a[i];
a[i] = tmp;
}
}
插入排序(O(n^2))
基本思想:把n个待排序的元素看成一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表。
for (int i = 0; i < a.length; i++) {
int insertVal = a[i];
int Index = i -1;
while (Index>=0&&insertVal<a[Index]){
a[Index+1] =a[Index]; //后移
Index--;
}
a[Index+1] =insertVal;
}
希尔排序(n*log2n)
基本思想:希尔排序是把序列按下标的一定增量分组(len/2 …/4 …/8),对每组使用直接插入排序算法排序;随着增量的逐渐减少,每组包含的数字越来越多,当增量减至1时,整个序列恰好被分为一组,算法便终止。
for (int gap = a.length / 2; gap > 0; gap /= 2) {
for (int i = gap; i < a.length; i++) {
int index = i;
int tmp = a[index];
if (a[index] < a[index - gap]) {
while (index-gap >= 0 && tmp < a[index - gap]) {
a[index] = a[index - gap];
index -= gap;
}
a[index] = tmp;
}
}
}
快速排序(n*log2n)
1.首先设置一个基准值,通过该基准值将数据分割成两部分。
2.将大于或等于基准值的数据交换到右边,小于基准值的数据交换到左边。一趟排序过后,左边部分中各个数据元素都小于分界值,而右边部分中各数据元素都大于或等于分界值。
3.然后,左边和右边的数据可以看成两组不同的部分,重复上述1和2步骤
4.当左右两部分都有序时,整个数据就完成了排序
public static void quickSort(int a[], int left, int right) {
if (left > right) return;
int l = left;
int r = right;
int flag = a[left];
int tmp;
while (l < r) {
while (a[r] >= flag && l < r) {
r--;
}
while (a[l] <= flag && l < r) {
l++;
}
if (l < r) {
tmp = a[l];
a[l] = a[r];
a[r] = tmp;
}
}
//l==r
a[left] = a[l];
a[l] = flag;
quickSort(a, left, l - 1);
quickSort(a, l + 1, right);
}
归并排序(n*log2n)
图解:来自https://blog.csdn.net/qq_33289077/article/details/90376759
public static void Merge(int a[], int left, int right, int mid, int[] temp) {
int l = left;
int r = mid + 1;
int pos = 0;//temp_pos
while (l <= mid && r <= right) {
if (a[r] < a[l]) {
temp[pos++] = a[r];
r++;
} else {
temp[pos++] = a[l];
l++;
}
}
while (l <= mid) temp[pos++] = a[l++];
while (r <= right) temp[pos++] = a[r++];
pos = 0;
int t = left;
while (t <= right) a[t++] = temp[pos++];
}
public static void MergeSort(int a[], int left, int right, int[] temp) {
if (left < right) {
int mid = (left + right) / 2;
MergeSort(a, left, mid, temp);
MergeSort(a, mid + 1, right, temp);
Merge(a,left,right,mid,temp);
}
}
基数排序(n*log2n)
将整数按位数切割成不同的数字,然后按每个位数分别比较。
public static void radixSort(int a[]) {
int max = a[0];
for (int i = 0; i < a.length; i++) {
if (a[i] > max) max = a[i];
}
int maxLength = Integer.toString(max).length();//数据中最大数位
int[][] bucket = new int[10][a.length];//桶
int[] bucketPos = new int[10];//每个桶的指针
int pos;//临时变量
for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
for (int j = 0; j < a.length; j++) {
pos = a[j]/n%10; //取某一位
bucket[pos][bucketPos[pos]] = a[j]; //放到对应桶中
bucketPos[pos] = bucketPos[pos]+1;//指针移动
}
int cnt = 0;
for (int j = 0; j < bucketPos.length ; j++) {
for (int k = 0; k < bucketPos[j]; k++) {
a[cnt++]=bucket[j][k]; //遍历所有桶,按顺序复制回原数组
}
bucketPos[j]=0;
}
System.out.println(i+": "+ Arrays.toString(a));
}
}
6、稀疏数组
面向对象
类:属性+方法。类是一种抽象的数据类型
对象:具体实例
本质:以类的方式组织代码。以对象的组织(封装)数据。
1、静态方法:
可以通过 类名.方法名 直接调用。
2、引用传递:
引用传递:对象,本质还是值传递
基础类型存的值是值,引用类型(对象)存的是地址,直接用这个地址操作属性就会改掉属性
3、使用new关键字创建对象
使用new关键字创建的时候,除了分配内存空间之外,还会给 创建好的对象进行默认的初始化 以及 对类中构造器的调用。
构造器:
(1)和类名相同
(2)没有返回值
构造器作用:
(1)使用new关键字,本质是在调用构造器
(2)初始化对象的值
注意点:
有参构造:一旦定义有参构造,无参构造就必须显式定义 alt+insert -constructer直接生成构造器
4、引用
引用类型、基本类型(8)
对象是通过引用来操作的:栈–》堆
对象的属性:默认初始化
- 数字: 0 0.0
- char: u0000
- boolean: false
- 引用:null
5、封装
属性私有private,数据的隐藏(禁止直接访问,通过接口访问)
get/set 对设置的属性进行判断 //alt+insert
1.提高程序的安全性,保护数据
2.隐藏代码细节
3.统一接口
4.增加系统可维护性
6、继承
子类(派生类)extands父类(基类)
JAVA 中只有单继承
子类继承了父类,就会拥有父类的全部方法(public).
创建子类时会默认先调用父类无参构造器super(),再调用子类构造器;若父类没有无参构造器,则子类必须在自己构造器中显式调用父类有参构造器.
super注意点
1.子类通过super调用父类的构造方法super(),必须在构造方法的第一个.
2.super必须只能出现在子类的方法或者构造方法中!
3.super 和this 不能同时调用构造方法
4.this:本身调用者这个对象(没有继承也可以使用,this();调用本类构造) super:代表父类对象的引用(有继承才能使用,super();调用父类构造)
方法重写
1.重写都是方法的重写,与属性无关
2.静态方法与非静态方法区别很大.静态方法:方法的调用只和左边,定义的数据类型有关.
3.static,final,private不能重写
4.final修饰的变量只能赋一次值;修饰的方法无法被覆盖,无法被重写;final修饰的引用只能永远指向该对象.
重写@override非静态的public方法:需要有继承关系,子类重写父类的方法.
- 方法名必须相同
- 参数列表必须相同
- 修饰符:范围可以扩大Pubilc>protected>Default>private
- 抛出的异常:范围可以被缩小不能被扩大.ClassNotFoundException
@override
//public void test();
A a = new A();
a.test();//a==>test
B b = new A();
b.test();//a==>test
7、多态
同一方法可以根据发送对象的不同而采用多种不同的行为方式。
// Person是Student的父类
Student s1 = new Student();
Person s2 = new Student();
Student s1 能调用的方法都是自己的或者继承父类的。
Person s2:父类的引用指向子类,不能调用子类独有的方法。只能调用Person类的方法,如果子类重写了Person类的方法,则调用的是子类中重写的方法。
注意:
- 多态是方法的多态,属性没有多态
- 父类和子类,有联系
- 存在条件:继承关系。方法需要重写,父类的引用指向子类对象! Father f1 = new Son()
XinstanceofY的结果:主要看实际对象的类型(右边)与Y是否有父子关系。
Person X = new Student();
Static
静态变量对于类而言在内存中只有一个,他被类中所有的实例共享。类名.变量名
非静态方法可以调用静态方法;静态方法可以调用静态方法,但不能调用非静态方法。
静态代码块:只执行一次,与类创建一起
匿名代码块:与对象同时产生
{//匿名代码块
System.out.println("nimingdaimakuai");
}
static {//静态代码块
System.out.println("static");
}
public Person() {
System.out.println("person");
}
8、抽象类
抽象方法,只有名字,没有实现。抽象类的所有方法其子类必须要实现,除非子类也是抽象类。
public abstract void doSomething();
1.不能new,只能靠子类实现
2.抽象类中可以写普通方法
3.抽象方法必须在抽象类中
9、接口interface
1.只有规范,定义一组规则。自己无法写方法,专业的约束,约束与实现分离,面向接口编程。
2.接口中默认所有定义的方法都是pubilic abstract;属性都是 pubilc static final常量。
3.接口都需要有实现类,实现了接口的类必须重写接口中的方法。(多继承)
4.接口不能被实例化,接口没有构造方法。
10、内部类
public class Outer {
private int id=6;
public void out(){
System.out.println(" outer function");
}
class Inner{
public void in(){
System.out.println(" in function");
}
public void getID(){
System.out.println(id);
}
public void getfun(){
out();
}
}
}
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.getfun();
}
11、异常
异常处理框架
JAVA把异常当作对象来处理,并定义了一个基类java.lang.Throwable作为所有异常的超类。
Error对象由java虚拟机生成并抛出,大多数错误与代码编写者无关,当出现这种异常时,JVM一般会选择终止线程。
catch(想要捕获的异常类型),假设要捕获多个异常,需要从小到大
int a = 1;
int b = 0;
try {
System.out.println(a/b);
}catch (Throwable e){
System.out.println("occur exception b=0");
}finally {
System.out.println("finally");
}
throw主动抛出异常,一般在方法中使用。
throws假如这个方法处理不了异常,方法上抛出异常。
public void test(int a, int b) throws ArithmeticException{
if(b==0){
throw new ArithmeticException();
}//抛出异常,要么在这个地方捕获(加上try catch),要么在方法上抛出异常(throws)交给调用方法的人捕获
a = a/b;
}
快捷代码
psvm
sout
100.for