JAVA基础——狂神(完结)

有一点java基础所以记笔记各有侧重,大家选择性食用就好

入门

hello world

java三大版本:JAVASE(标准版,桌面程序、控制台),JAVAME(嵌入式), JAVAEE(企业级,web端,服务器)

JDK:java development kit,除了java/javac/jar,包括JRE和JVM

JRE:java runtime environment,包含JVM,只需要运行环境可以安装JRE

JVM:java virtual machine,跨平台的核心

卸载安装

卸载jdk: 删除jdk安装目录、删除JAVA_HOME和path下相关的环境变量、cmd查看java -version
安装jdk8: oracle下载安装、配置JAVA_HOME和path的环境变量、cmd输入java -version

java运行机制

编写java程序:新建.java文件,javac编译生成class文件,java运行class文件(不需要.java)
**编译型:**源代码全部转换为可执行代码,执行速度快,操作系统常用
**解释型:**逐句解释,网页常用(对速度要求不高)
随着硬件发展,编译和解释界限逐渐模糊
java代码在JVM前先编译,到操作系统前再解释

基础语法

注释

单行:// 注释;多行:/*注释*/;
文档注释:javadoc,/**注释*/

标识符

关键字:java规定过的名字,不能用关键字再命名类、变量或者方法
String不是关键字,是一个类
关键字
标识符只能以字母、下划线或$开头,可包含字母、数字、_、$,大小写敏感,可使用中文

数据类型

强类型语言:变量必须先定义后使用,java/c++,安全性高但速度慢
弱类型语言:VB/JS

八大基本类型

基本数据类型
定义long需要在数字后加上L,float在后面加上F
位(bit):计算机存储最小单位
字节(byte):数据处理的基本单位,1B=8bit

整数进制

二进制0b开头,八进制0开头,十六进制0x开头

浮点数问题

float运算问题
float和double不相等问题
浮点数是有限且离散的,存在舍入误差,只是接近但不等于具体数值
最好避免浮点数进行比较,尤其是double和float的比较
银行业务中采用BigDecimal数学工具类

字符

字符本质还是数字,可以通过(int)进行强制类型转换
unicode编码,‘a’=97=‘\u0061’,‘A’=65,U0000-UFFFF共2^16
转义字符:\t, \n等
String类的相等关系

类型转换

byte,short,char–>int–>long–>float–>double
强制转换:高->低,容易出现内存溢出或精度问题
自动转换:低->高
注意:不能对bool进行转换
较大数字的表示
溢出问题

引用类型——类、接口、数组

变量

变量包括变量名、类型、作用域
作用域:
类变量:static定义,从属类
实例变量:方法外面,类里面,从属于对象,默认值为0/null/false
局部变量:方法里面,必须声明和初始化
作用域命名规范

常量

初始化后不再改变,final定义,一般使用大写字符和下划线

运算符

关系运算符:instanceof
条件运算符:? :(三元运算符)
自增自减:++,–(一元运算符)
自增运算
ctrl+D 复制当前行到下一行
运算结果的类型
短路

位运算

&、|、~、^、>>、<<、效率高
次幂运算怎么最快: 2<<3=16
<<表示*2,>>表示/2

字符串连接符

+两侧出现String,则为字符串,否则为加法运算
字符串连接

优先级

多用()

包机制

用于组织类,区别类名的命名空间(不同包可以有同名类,但互相import时会报错)
包名
《阿里巴巴开发手册》

javaDoc

生成自己的API文档,@parameter 参数名
javadoc

package com.lqr;
/** 类的注释
 * @author lqr
 * @version 1.0
 * @since 20221115
 */
public class hello {
    String name;
    /**方法的注释
     * @parameter none
     * @return name
     * @throws Exception
     */
    public String getName() throws Exception{
        return name;
    }
}

终端打开文件夹,输入以下命令,生成的文件中index.html可以从浏览器打开

javadoc -encoding UTF-8 -charset UTF-8 xxx.java

流程控制

用户交互Scanner

next和nextLine

Scanner类获取用户输入,通过Scanner类的next()与nextLine()方法获取输入的字符串,
在读取前一般需要使hasNext()与hasNextLine()判断是否还有输入的数据
IO流为了避免占用资源,养成close习惯

Scanner scanner = new Scanner(System.in);
if(scanner.hasNextLine()){
    String str = scanner.nextLine();//输入:  123  23
    System.out.println(str);        //输出:  123  23
}
if(scanner.hasNext()){
    String str = scanner.next();//输入:  123  23
    System.out.println(str);    //输出:123(没有空格)
}
scanner.close();

next会自动去掉有效字符前的空格,有效字符后的空格作为结束,不能接受带有空格的字符串
nextLIine以回车结束,可以获得空白

scanner接收其他类型

hasNextInt(),hasNextFloat()等,
用while,则以非数字为结束符;用if,则以回车为结束符

Scanner scanner = new Scanner(System.in);
double sum = 0;
int n = 0;
//scanner 输入多个数字 以非数字结束 求总和、均值
while(scanner.hasNextDouble()){
     double i = scanner.nextDouble();
     sum += i;
     n++;
}
System.out.println("sum: "+ sum);
System.out.println("avg: "+ sum/n);
scanner.close();//IO流为了避免占用资源,养成close习惯

顺序、选择、循环

switch

switch语句谨记case后加上break
IDEA项目结构中可以查看编译后的claa文件位置,用IDEA可以直接打开反编译后的class文件
javaSE7开始,switch支持String类型

switch(xxx){
	case xxx:
		...;
		break;
	case xxx:
		...;
		break;

for

print不换行,println输出完换行
IDEA for循环快捷:10.for——for(int i = 0; i < 10; ++i)

//打印九九乘法表
for(int i=1; i<10; ++i){
    for(int j=1; j<=i; ++j){
        System.out.print(j+"x"+i+"="+(i*j)+"\t");
    }
    System.out.println("");
}
增强for
int[] a = {1,2,3}
for(int x:a){
	System.out.println(x);
}

break/continue/goto

java没有goto,但有带标签的break和continue
对Java来说唯一用到标签的地方是在循环语句之前
在循环之前设置标签的唯一理由是:希望在其中嵌套另一个循环,使得break和continue可以中断到存在标签的地方。

outer: for(int i = 101; i<150; ++i){
        for(int j=2; j<i/2; j++){
            if(i % j==0)
                continue outer;//这里用break是一样的
        }
        System.out.println(i);
    }
//打印五行三角形
for (int i = 0; i < 5; i++) {
            for (int j = 5; j > i; j--) {
                System.out.print(" ");//左上角空白
            }
            for (int j = 0; j <= i; j++) {
                System.out.print("*");//左下角
            }
            for (int j = 0; j < i; j++) {
                System.out.print("*");//右下角
            }
            System.out.println("");
        }
//方法二
int n = 5;
for (int i = 0; i < n; i++) {
    for (int j = 0; j < n-i-1; j++) {
        System.out.print(" ");//左上角空白
    }
    for(int j=1; j<=2*i+1; j++){
        System.out.print("*");//每行*的数量为奇数
    }
    System.out.println("");
}

方法

定义

修饰符+返回类型+方法名+参数(形参/实参)+方法体
方法调用
return即可以返回值,也可以终止方法

调用

  1. 静态方法调用:类名.方法名 直接调用
  2. 非静态方法:用new实例化类,用对象名.方法名调用
  3. 静态方法中无法调用非静态方法:静态方法与类一起加载的,非静态方法在类实例化后才能使用

值传递和引用传递

Java是值传递

public class test{
	public void seta(int a){
	    a =10;
	}
	public static void main(String[] args) {
	    int a = 1;
	    System.out.println(a);//1
	    new Student().seta(a);
	    System.out.println(a);//1
	}
}

对象是引用传递

public class student{
	String name;
	public void setName(String name){
        this.name = name;
    }
    public static void main(String[] args) {
        Student student = new Student();
        System.out.println(student.name);//null
        student.setName("lqr");
        System.out.println(student.name);//lqr
    }
}

重载

**规则:**名字一样、参数列表不同(个数或类型或顺序)

public static int max(int a, int b){
        return a>b?a:b;
}
public static int max(int a, int b, int c){
    if(a>b){
        return a>c?a:c;
    }
    else{
        return b>c?b:c;
    }
}
public static double max(double a, double b){
    return a>b?a:b;
}

命令行传参

希望运行一个程序时候再传递给它消息。这要靠传递命令行参数给main()函数实现

public class hello {
    public static void main(String[] args) {
        for(int i=0; i<args.length; i++){
            System.out.println("args["+i+"]: "+args[i]);
        }
        
    }
}

命令行传参
要回退到src下才能运行class文件

可变参数

本质是数组
在方法声明中,在指定参数类型后加一个省略号(….),可以获得不定项的参数,但这些参数类型必须相同
一个方法中只能指定一个可变参数,它必须是方法的最后一个参数

递归

递归头(什么时候调用结束)+递归体(什么时候调用)
边界条件+前阶段+返回阶段——Java的栈机制,递归调用次数太多容易栈溢出

public static int fun(int n){//递归求阶乘
    if(n==1)//边界条件
        return 1;
    else
        return n*fun(n-1);
}

数组

同类型数据的有序集合,按下标访问
数组元素可以是基本类型或引用类型(任何类型)
数组变量属于引用类型,可以看成对象,数组元素相当于成员变量

声明创建

java使用new创建数组,用来开辟空间,一经创建无法改变

int[] a;//声明,在栈里有a
int a[]//C/C++
a = new int[10];//创建,在堆里有a指向的十个int的空间
a[2] = 3;//赋值
a.length;//数组的length属性

静态初始化

直接在定义的时候赋值(初始化),同时确定了长度

int[] a = {1,2,3};

动态初始化

先创建,后赋值

int[] a = new int[2];
a[0] = 1;
a[1] = 2;
默认初始化

数组是引用类型,它的元素相当于类的实例变量,一经分配空间,每个元素也被按照实例变量同样的方式被隐式初始化

int[] a = new int[2];//此时a[0]和a[1]均为0

java内存

数组声明时在栈里有变量,指向创建时在堆里的空间
new出来的都在堆里
内存

使用

public static int[] reverse(int[] n){//反转数组
    int[] m = new int[n.length];
    for (int i = 0, j = n.length-1; i < n.length; i++, j--) {
        m[j] = n[i];//j从length-1开始
    }
    return m;
}

多维数组

int[][] a = new int[2][3];//两行三列数组
for(int i = 0; i < a.length; ++i){
	for(int j = 0; j < a[i].length; ++j){//遍历二维数组
		...
	}
}

Arrays类

数组的工具类java.util.Arrays,Arrays类中的方法可以直接使用类名进行调用

int[] a = {1,3,23,44,112,452,12,34,23124};
Arrays.sort(a);//升序排序(无返回值,修改本身
Arrays.fill(a, 0);//用0赋值每个元素,无返回值,修改本身
Arrays.fill(a, 1, 3, 0);//用0赋值1和2下标的元素,无返回值,修改本身
System.out.println(Arrays.toString(a));//利用Arrays打印数组

冒泡排序

public static int[] sort(int[] a){
    int temp;
    boolean flag;
    for (int i = 0; i < a.length; i++) {
        flag = false;//尚未排序
        for(int j = 0; j<a.length-1-i; j++){
            if(a[j]>a[j+1]){//升序排序,降序只需把>改成<
                temp = a[j+1];
                a[j+1] = a[j];
                a[j] = temp;
                flag = true;//执行了排序操作
            }
        }
        if(!flag)//这一轮没有执行排序操作,说明已经有序,提前跳出
            return a;
    }
    return a;
}

稀疏数组

数组存在大量同值元素时,

  1. 记录数组几行几列,多少个不同值
  2. 不同值的元素位置和值记录在小规模数组中
    稀疏数组
public static int[][] array(int[][] a){//稀疏数组存储为小数组
    int[][] arr;
    int sum = 0;
    for (int i = 0; i < a.length; i++) {//统计有效值
        for (int i1 : a[i]) {
            if(i1!=0)
                sum++;
        }
    }
    arr = new int[sum+1][3];//创建稀疏数组
    arr[0][0] = a.length;
    arr[0][1] = a[0].length;
    arr[0][2] = sum;
    sum = 1;
    for (int i = 0; i < a.length; i++) {
        for (int j = 0; j < a[i].length; j++) {//稀疏数组赋值
            if(a[i][j]!=0){
                arr[sum][0] = i;
                arr[sum][1] = j;
                arr[sum++][2] = a[i][j];
            }
        }
    }
    return arr;
}
public static int[][] array2(int[][] a){//小数组转换为稀疏数组
    int[][] arr = new int[a[0][0]][a[0][1]];
     for (int i = 1; i <= a[0][2]; i++) {//填充有效值
         arr[a[i][0]][a[i][1]] = a[i][2];
     }
     return arr;
 }

面向对象OOP

面向过程->面向对象(适合处理需要多人协作的问题)
面向对象编程的本质就是以类的方式组织代码,以对象的方式组织(封装)数据
从认识的角度是先有对象再有类,从代码的角度是先有类再有对象
一个项目应当只存在一个main方法入口

对象

创建

使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。

构造器(构造方法)

设置-项目结构-添加根目录-选择out文件夹添加,out中为class文件,会为类自动添加构造方法
**构造器的特点:**名字必须和类名相同;没有返回类型也不写void
**构造器作用:**初始化对象的值
注意:

  1. 使用new关键字实际上是在调用构造器
  2. 一旦定义了有参构造,就必须显式定义无参构造,否则报错
    快捷键alt+insert生成构造器

三大特性

封装

高内聚:内部数据操作细节由自己完成,不允许外部干涉
低耦合:尽量暴露少量方法供外部使用
属性私有;get/set
private属性外部无法直接访问,对象也无法直接调用
作用:提高安全性,保护数据,隐藏代码细节,统一接口,提高可维护性

public class Student {
	private String name;
	private int age;
	private boolean gender;
	
	public String getName() {
	    return name;
	}	
	public int getAge() {
	    return age;
	}	
	public boolean getGender() {
	    return gender;
	}	
	public void setGender(boolean gender) {
	    this.gender = gender;
	}	
	public void setName(String name){
	    this.name = name;
	}	
	private void setAge(int age) {
		if(age>200 || age<0)
			this.age = 0;
	    else
	    	this.age = age;
	}
}
继承extends

JAVA中类只有单继承,没有多继承
子类和父类是“is a”的关系,除了继承,java中类之间的关系还有组合、聚合等
子类继承父类,会拥有父类的全部方法(private除外)
快捷键ctrl+h,展示继承关系树

java中所有类默认继承Object类,getClass方法可以获得当前类

super
public class Person {
    private String name;
    private int age;
    private boolean gender;
    protected int money = 10_0000_0000;
}
public class Student extends Person{
    private int money = 1000;
    public void print(){
        System.out.println(money);//1000
        System.out.println(this.money);//1000
        System.out.println(super.money);//10_0000_0000
    }
    public static void main(String[] args) {
        Student lqr = new Student();
        lqr.print();
    }
}

this访问当前类,super访问父类
构造对象时,先调用父类构造器,再调用子类构造器
注意:

  1. 使用super()调用父类构造方法,必须在构造方法的第一句
  2. super只能出现在子类的方法中,表示父类对象的引用
  3. super和this不能同时调用构造方法,因为两个都必须在第一句
方法重写

注意:

  1. 方法名必须相同,参数列表必须相同(参数列表不同的叫重载)
  2. 修饰符权限范围可以扩大,不能缩小
  3. 抛出异常的范围可以缩小,不能扩大
  4. static/final/private方法不能重写
    多态
    **静态方法:**父类的引用指向子类,方法的调用只和定义的类型有关(new的左边)
    重写
    **非静态方法:**子类重写父类的方法后,只调用子类方法
    快捷键alt+insert,override生成重写方法
多态

new方法新建对象,实际类型确定,但指向的引用类型不确定
子类能调用的方法包括继承的方法和自己的方法
父类的引用指向子类时,不能调用子类的方法,可以通过强制转换再调用
注意:

  1. 多态是方法的多态,和属性无关
  2. 有继承关系,有方法重写,父类引用指向子类对象时,才是多态
instanceof 引用类型转换

instanceof判断对象实际类型与类之间是否有继承关系

public class Student extends Person{
    public static void main(String[] args) {
        Object o = new Student();
        System.out.println(o instanceof Student);//true
        System.out.println(o instanceof Person);//true
        System.out.println(o instanceof Teacher);//false
        System.out.println(o instanceof String);//false
        System.out.println("==========");
        Person p = new Student();
        System.out.println(p instanceof Student);//true
        System.out.println(p instanceof Person);//true
        System.out.println(p instanceof Teacher);//false
//        System.out.println(p instanceof String);//报错
        System.out.println("==========");
        Student s = new Student();
        System.out.println(s instanceof Student);//true
        System.out.println(s instanceof Person);//true
//      System.out.println(s instanceof Teacher);//报错
//      System.out.println(s instanceof String);//报错
    }
}

子类转换为父类可以直接转换,但可能会丢失方法
父类转子类需要强制转换,转换后才能调用子类的方法

static

静态属性

既可以用类来调用,也可以用对象来调用,若在类里面,还可以直接调用
静态属性是属于类的,建议使用类名.来调用

静态方法

既可以用类来调用,也可以用对象来调用,若在类里面,还可以直接调用


静态代码块只在第一次创建对象时执行一次;
匿名代码块中可以用来赋初始值;

import static java.lang.Math.random;//静态导入包,可以直接调用
public static void main(String[] args) {
        double r = random();
}

final修饰的类不能再被继承

抽象类

abstract修饰类名,abstract修饰方法名时,没有方法体

public abstract class Person {
    public abstract void say();
}

注意:

  1. 抽象类的子类都必须实现它的抽象方法,除非子类也是抽象类
  2. 抽象类不能new一个对象,只能通过子类来实现
  3. 抽象类中可以有非抽象方法,抽象方法只能存在于抽象类中

接口

类是单继承,但接口是多继承
普通类:只有具体实现
抽象类:具体实现和规范(抽象方法)都有
接口:只有规范!!自己无法写方法体,约束和实现分离,面向接口编程
接口定义
接口中的所有方法都不能有方法体,都是public abstract,所有属性都是public static final;
接口通过interface定义,实现类通过implements实现;
一个类可以实现多个接口——多继承;
实现接口必须重写接口中的方法;
接口不能被实例化,没有构造方法

内部类

public class hello {
    private int id=10;
    public void out(){
        System.out.println("外部类方法");
    }
    class Inner{
        public void in(){
            System.out.println("内部方法");
        }
        public int getId(){
			return id;//内部类可以获得外部类的私有属性
		}
    }
}
public abstract class Person {
    public static void main(String[] args) {
        hello hello = new hello();
        hello.Inner inner = hello.new Inner();//通过外部类实例化内部类
        inner.in();//内部方法
    }
}


不能通过外部类实例化静态的内部类
一个java文件中只能有一个public class,但可以有多个class

public class hello {
    private int id;
    public void out(){
        class Inner{//局部内部类
            public void in(){
                System.out.println("内部方法");
            }
        }
        System.out.println("外部类方法");
    }
    public static void main(String[] args) {
    }
}

匿名初始化类,new XXX().XX();,不用把实例保存到变量中

异常

检查性异常:用户错误引起,程序员无法预见(例如,文件不存在)
运行时异常:在编译时可以被忽略,但程序员可以避免
错误:错误不是异常,是脱离程序员控制的问题,在代码中经常被忽略,例如栈溢出

java的异常处理机制


error由java虚拟机生成并抛出,与程序员无关,出现时JVM会终止线程
exception程序中可以捕获处理

处理异常

int a = 1;
intb = 0;
try {
    System.out.println(a/b);
}catch (ArithmeticException e){
    System.out.println("除0了!!!");
}finally {
    System.out.println("无论是否异常都会执行");
}

catch可以叠加,捕获多个异常,但最大的异常应该在最下面,否则会执行不到

快捷键ctrl+alt+t,自动对选中的代码生成try catch finally语句块

抛出异常


主动抛出异常:throw关键字,一般在方法中使用

方法抛出异常:throws关键字,在调用时可以捕获

自定义异常

  1. 创建异常类,继承Exception类
  2. 在方法中通过throw抛出异常
  3. 如果在当前方法抛出异常并处理,要用try-catch捕获处理
  4. 如果在方法声明时throws异常,在方法调用时try-catch捕获处理
public void a(int aa){//方法定义时处理异常
    if(aa>10){
        try {
            throw new MyException(aa);
        } catch (MyException e) {
            throw new RuntimeException(e);
        }
    }
}
public void a(int aa) throws MyException {//方法调用时处理异常
    if(aa>10){
        throw new MyException(aa);
    }
}
//一个例子
public class MyException extends Exception{
    private int a;
    public MyException(int a) {
        this.a = a;
    }
    @Override
    public String toString() {//打印信息
        return "MyException{"+"a="+a+"}";
    }
}
public static void main(String[] args) {
    try {
        hello.test(99);
    } catch (MyException e) {
        System.out.println("myexception  "+e);//exception类中的toString方法用来打印e
    }
}
public static void test(int aa) throws MyException {
    System.out.println("aa进来");
    if(aa>10){
        throw new MyException(aa);
    }
    System.out.println("异常结束");
}

注意:

  1. 在catch的最后加一个catch(Exception e)来处理可能遗漏的异常
  2. 对不确定的代码可以加上try-catch处理潜在异常
  3. 尽量增加自己对异常的处理操作
  4. 尽量添加finally释放占用的资源
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值