Java学习笔记01 - JavaSE基础

在线工具

java https://c.runoob.com/compile/10

在线编写运行 Java 8 https://www.tutorialspoint.co...

SQL 在线运行 https://www.bejson.com/runcod...

Java牛客题库 https://www.nowcoder.com/inte...

JDK, JRE, JVM

  • JDK : Java Development Kit
  • JRE : Java Runtime Enviroment
  • JVM : Java Virtual Machine

输出Hello Wolrd

vim Hello.java
public class Hello{
    public static void main(String[] args){
        System.out.print("Hello World!");
    }
}

编译

javac Hello.java

执行

java Hello

输出

Hello World!

Java程序运行机制

  • 编译型:
  • 解释型:
  • 程序运行机制:

    源文件(*.java) => Java编译器 => 字节码(.class)

    => JVM ( 类装载器 =>字节码校验器 => 解释器 )

    => 操作系统平台

IDEA

新建工程

File => New => Project… => Empty Project

File => Project Structure => Project => Project SDK (1.8.0) => Project language level (8) => OK

基础语法

1.注释,标识符,关键字

注释
//单行注释
/* 多行注释 */
/**
  * 文档注释
  * @Author itxiaoma
  */
标识符
类名,变量名,方法名都称为标识符
  • 标识符以字母,美元($),下划线(_)开始
  • 首字母后可以是字母,美元($),下划线(_),数字的组合
  • 不能使用关键字作为变量名,方法名
  • 大小写敏感
关键字(50+)

Java学习笔记01 - JavaSE基础_第1张图片

2.数据类型

强类型语言:变量使用必须严格符合规定,所有变量都必须先定义后才能使用
Java数据类型
  1. 基本类型:(8大基本类型)

    1. 数值

      1. 整数

        1. byte:1个字节(-128~127)
        2. short:2个字节(-32768~32767)
        3. int:4个字节(-2147483648~2147483647)21亿+
        4. long:8个字节(例:long num=40L;)
      2. 浮点

        1. float:4个字节(例:float num=40F;)
        2. double:8个字节
      3. 字符串char:2个字节
    2. boolean:1位,true/false
  1. 引用类型:类,接口,数组

注1:String不是数据类型,是类

注2:1bit表示1位;(bit是计算机内部数据存储的最小单位)

​ 1Byte表示1个字节,1B=8b;

​ 1KB = 1024B;

​ 1MB = 1024KB;

​ 1GB = 1024MB;

​ 1TB = 1024GB;

Java数据类型的常见问题
  1. 整数扩展

    int a = 10;
    int b = 010;//八进制
    int c = 0x10;//十六进制
  2. 浮点型扩展

    float f = 0.1f;
    double d = 1.0/10;
    System.out.println(f==d);//false
    
    float d1 = 123123123123f;
    float d2 = d1 + 1;
    System.out.println(d1==d2);//true
    
    //float 有限 离散 舍入误差 接近但不等于
    //不要用浮点数进行比较
    //数学工具类BigDecimal
  3. 字符类扩展

    char a = 'a';
    System.out.println((int)a);//97
    char a1 = '\u0061';
    System.out.println(a1);//a
    //所有的字符本质还是数字
    
    转义字符:
    \t 制表符
    \n 换行
    ...

3.类型转换

运算中,不同类型的数据会先转换位同一类型,再进行计算

优先级:低 ==> 高

byte,short,char => int => long => float => double

自动转化:低 => 高

强制转换: 高 => 低 (类型)变量名

注1:

  1. 不能对布尔值进行转换
  2. 不能把对象类型转为不相干的类型
  3. 高容量转低容量,会有内存溢出或精度问题

注2:JDK7的新特性,数字间可以用下划线分割(1000 = 1_000)

4.变量、常量、作用域

变量
int a = 1;
常量 - final
常量:初始化后不能改变,一般为大写
static final double PI = 3.14;
作用域
  1. 类变量
  2. 实例变量
  3. 局部变量
public class Hello {
    //类变量:static
    static int a = 1;
    //实例变量:属于对象,不需要初始化(会自动初始化为类型默认值)
    //布尔值默认false,除基本类型以外其他变量都是null
    String b;
    public static void main(String[] args) {
        System.out.println(a);

        int c = 3;//局部变量:必须声明和初始化
        System.out.println(c);

        Hello obj = new Hello();
        System.out.println(obj.b);//null
    }
}
命名规则:
  1. 类变量,局部变量,方法名:驼峰(首字母小写)
  2. 常量:大写 + 下划线
  3. 类型:驼峰(首字母大写)

5.基本运算符

  1. 算术运算符:+, -, *, /, %, ++, --
  2. 赋值运算符:=
  3. 关系运算符:>, <, >=, <=, ==, !=, instanceof
  4. 逻辑运算符:&&,||,!
  5. 位运算符:&, |, ^, ~, >>, << , >>>
  6. 条件运算符:? :
  7. 扩展赋值运算符:+=, -=, *= ,/=

例:

long a = 123L;
int b = 123;
short c = 10;
byte d = 8;
System.out.println(a+d);//long
System.out.println(b+c);//int
System.out.println(c+d);//int
//结论:有long类型时转long,否则转int

幂运算:2^3

double pow = Math.pow(2, 3);
System.out.println(pow);//8.0

位运算

<< 乘2 
>> 除2

6.包机制

包的本质就是文件夹
  1. 包机制是为了更好地组织类,用于区别类名的命名空间
  2. 一般用公司名倒置作为报名 pakage com.baidu.www;
  3. 使用import导入包(import 包名.* 表示导入包下所有类)

7.JavaDoc生成文档

注释参数

/**
 * @author 作者
 * @version 版本
 * @since 需要最早使用的jdk版本
 * @param 参数
 * @return 返回值
 * @throws 异常抛出
 */

中文编码

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

流程控制

1.用户交互Scanner (Java5新特性)

基础使用

import java.util.Scanner;

public class Demo {
    public static void main(String[] args) {
        //创建扫描器对象,用于接收键盘数据
        Scanner s = new Scanner(System.in);
        //判断用户输入
        if(s.hasNextLine()){
            String str = s.nextLine();
            System.out.println(str);
        }
        //IO流的类会一直占用内存,用完需要关闭
        s.close();
    }
}
//next()以空格为结束符,nextLine()以回车为结束符

使用进阶

计算多个数字的总和与平均数,非数字结束
Scanner s = new Scanner(System.in);
double sum = 0;
int num = 0;
while(s.hasNextDouble()){
    double x = s.nextDouble();
    sum += x;
    num++;
}
System.out.println("和是:" + sum);
System.out.println("平均值是" + (sum/num));
s.close();

2.九九乘法表

/*
1*1=1    
2*1=2    2*2=4    
3*1=3    3*2=6    3*3=9    
4*1=4    4*2=8    4*3=12    4*4=16    
5*1=5    5*2=10    5*3=15    5*4=20    5*5=25    
6*1=6    6*2=12    6*3=18    6*4=24    6*5=30    6*6=36    
7*1=7    7*2=14    7*3=21    7*4=28    7*5=35    7*6=42    7*7=49    
8*1=8    8*2=16    8*3=24    8*4=32    8*5=40    8*6=48    8*7=56    8*8=64    
9*1=9    9*2=18    9*3=27    9*4=36    9*5=45    9*6=54    9*7=63    9*8=72    9*9=81    
*/
for (int m = 1; m <= 9; m++) {
    for (int n = 1; n <= m; n++) {
        System.out.print(m + "*" + n + "=" + (m * n) + "\t");
    }
    System.out.println();
}
//System.out.print 不换行输出

3.增强for循环(JDK1.5新特性)

int[] numbers = {1, 2, 3, 4, 5};
for (int x : numbers) {
     System.out.println(x);
}

4.label

打印101 - 150间的所有质数
outer:for (int i = 101; i <= 150; i++) {
    for (int j = 2; j < i / 2; j++) {
        if (i % j == 0) {
            continue outer;
        }
    }
    System.out.println(i);
}

Java方法

方法是用来完成特定功能的代码片段,由方法名和方法体组成

方法名:修饰符 返回值类型 方法名 (参数类型 参数名){}

方法体:return 返回值;

参数类型:实参,形参

注:java都是值传递,没有引用传递

1.方法的重载

重载就是在一个类中,有相同的函数名称,但形参不同的函数

方法重载规则:

  1. 方法名称必须相同
  2. 参数列表必须不同(个数,类型,参数顺序不同)
  3. 返回类型可相同可不同

2.命令行传参

程序运行时传递参数,可以通过main方法传递
public static void main(String[] args) {
    for (int i = 0; i < args.length; i++) {
        System.out.println(args[i]);
    }
}

3.可变参数(JDK1.5新特性)

public static void main(String[] args) {
    test(1,2,3);
}
public static void test(int... i){
    System.out.println(i[0]);
    System.out.println(i[1]);
    System.out.println(i[2]);
}

4.递归

递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。

递归体:什么时候需要调用自身方法。

Java数组

数组是相同类型数据的有序集合
dataType[] arrayRefVar = new dataType[size];

int nums[] = new int[10];
//二维数组
int[][] n = new int[2][2];
int[][] n = {{1,2},{3,4}} 

基本特点

  1. 长度是确定的,一旦创建,长度不可变
  2. 元素类型必须相同
  3. 数组对象本身在堆中(数组是引用类型,可看做对象,数组元素相当于对象的成员变量,Java的对象在堆中)

内存分析

graph LR
A(java内存)
A --> B(堆)
      B -->B1[存放new的对象和数组]
      B -->B2[可以被所有线程共享,不会存放别的对象引用] 
A --> C(栈)
      C -->C1[存放基本变量类型,包含具体数值]
      C -->C2[引用对象的变量,存放引用在堆中的地址] 
A --> D(方法区)
      D -->D1[可以被所有线程共享]
      D -->D2[包含所有calss和static变量] 
//1.声明数组
int[] nums;//在栈中
//2.创建数组
nums = new int[10];//在堆中

三种初始化状态

//静态初始化
int[] a = {1, 2, 3};
Man[] mans = {new Man(1),new Man(2)}

//动态初始化(包含默认初始化)
int[] b = new int[10];//默认分配10个0
b[0] = 10;

注:数组是引用类型,数组元素相当于类的实例变量,数组创建时分配空间,数组元素也会按默认值初始化。

数组工具类java.util.Arrays

打印数组元素 Arrays.toString(a);
数组填充 Arrays.fill(a, 0 , 1, 0); 数组下标0-1的元素用0填充
数组排序 Arrays.sort(a);
比较数组 equals
查找数组元素 binarySearch 对排序好的数组进行二分法查找

冒泡排序

  1. 共有八大排序
  2. 时间复杂度为O(n2)

稀疏数组

当一个数组中大部分元素为0或值相同时,可以使用稀疏数组保存

处理方式:

1.记录数组行列数,不同值数

2.把不同值的元素行列信息,元素值记录在小规模数组中

/*
稀疏数组
1    2    1
2    3    2
还原数组
0    0    0    0    0    0    0    0    0    0    0    
0    0    1    0    0    0    0    0    0    0    0    
0    0    0    2    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    0    0    0    0    
*/
public class Demo {
    public static void main(String[] args) {
        int[][] array1 = new int[11][11];
        array1[1][2] = 1;
        array1[2][3] = 2;
        int sum = 0;
        for (int i = 0; i < 11; i++) {
            for (int j = 0; j < 11; j++) {
                if (array1[i][j] != 0) {
                    sum++;
                }
            }
        }
        int[][] array2 = new int[sum + 1][3];
        array2[0][0] = 11;
        array2[0][1] = 11;
        array2[0][2] = sum;
        int count = 0;
        for (int i = 0; i < array1.length; i++) {
            for (int j = 0; j < array1[i].length; j++) {
                if (array1[i][j] != 0) {
                    count++;
                    array2[count][0] = i;
                    array2[count][1] = j;
                    array2[count][2] = array1[i][j];
                }
            }
        }
        System.out.println("稀疏数组");
        for (int j = 1; j < array2.length; j++) {
            System.out.println(array2[j][0] + "\t" + array2[j][1] + "\t" + array2[j][2]);
        }
        System.out.println("还原数组");
        int[][] array3 = new int[array2[0][0]][array2[0][1]];
        for (int j = 1; j < array2.length; j++) {
            array3[array2[j][0]][array2[j][1]] = array2[j][2];
        }
        for (int[] ints : array3) {
            for (int num : ints) {
                System.out.print(num + "\t");
            }
            System.out.println();
        }
    }
}

面向对象

以类的方式组织代码。以对象组织(封装)数据

三大特性:封装,继承,多态

1.创建类与对象

一个项目应该只存在一个main方法
创建对象
使用new创建对象时,除了分配内存空间,还会给创建好的对象进行默认初始化,及调用类中的构造器。

com/oop/demo/Application.java

package com.oop.demo;
public class Application {
    public static void main(String[] args) {
        //类:抽象的,实例化后会返回一个自己的对象
        Student xiaoming = new Student();
        Student xiaohong = new Student();
        xiaoming.name = "小明";
        xiaoming.age = 20;
        xiaohong.name = "小红";
        xiaohong.age = 21;
        System.out.println("姓名:" + xiaoming.name + "\t年龄:" + xiaoming.age);
        xiaoming.study();
        System.out.println("姓名:" + xiaohong.name + "\t年龄:" + xiaohong.age);
        xiaohong.study();
    }
}

com/oop/demo/Student.java

package com.oop.demo;
public class Student {
    //属性
    String name;
    int age;
    //方法
    public void study() {
        System.out.println(this.name + "在学习");
    }
}
构造器(构造方法)
  1. 必须和类名相同
  2. 必须没有返回类型(不能写void)
  3. 一旦定义了有参数的构造器,new对象时想不传参数,就必须写一个无参数构造器
public class Student {
    //属性
    String name;
    int age;
    //无参(默认)构造器
    public Student(){
        
    }
    //有参
    public Student(String name){
        this.name = name;
    }
    public Student(String name,int age){
        this.name = name;
        this.age = age;
    } 
}

创建对象内存分析

public class Application {
    public static void main(String[] args) {
        //类:抽象的,实例化后会返回一个自己的对象
        Student xiaoming = new Student();
        Student xiaohong = new Student();
        xiaoming.name = "小明";
        xiaoming.age = 20;
        xiaohong.name = "小红";
        xiaohong.age = 21;
        System.out.println("姓名:" + xiaoming.name + "\t年龄:" + xiaoming.age);
        xiaoming.study();
        System.out.println("姓名:" + xiaohong.name + "\t年龄:" + xiaohong.age);
        xiaohong.study();
    }
}

方法区也在堆中;

静态方法区和类一起加载,所以静态方法可以直接调用,不需要实例化

  1. 加载Application和Student类信息到方法区
  2. 加载main()方法到栈中
  3. 加载xiaoming和xiaohong引用变量名到栈中
  4. 加载Student xiaoming = new Student();和Student xiaohong = new Student();实例到堆中
  5. xiaoming和xiaohong调用方法区的study方法

注:基本类型外的变量都是引用类型,是通过引用来操作的;引用名在栈中,指向对象实体在堆中的地址。

封装

禁止直接访问一个对象中数据的实际表示,应通过接口操作来访问。

属性私有(private),get/set

public class Student {
    private String name;
    private int age;
    public String getName() {
        return this.name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int getAge() {
        return age;
    }
}

继承extends

继承的本质是对某一批类的抽象,从而实现更好的建模;

继承是类之间的关系,子类继承(extends)父类的全部public方法;

私有的属性和方法无法被继承

注:

  1. Java中只有单继承,没有多继承 (一个子类只能有一个父类)
  2. Java中所有类,都默认直接或间接继承Object类

Super

注意点
  1. super调用父类的构造方法,必须在构造方法的第一行
  2. super只能出现在子类的方法或构造方法中
  3. super和this不能同时在构造方法中调用(都需要在第一行)
super和this的区别
this super
代表对象不同 调用者本身的对象 父类对象的引用
使用前提不同 没有继承也能使用 只能在有继承时使用
调用构造方法不同 调用本类的构造方法 调用父类的构造方法

com/oop/demo/Application.java

package com.oop.demo;

public class Application {
    public static void main(String[] args) {
        Student xiaoming = new Student();
        xiaoming.test1();
        //Person无参构造
        //Student无参构造
        //Student
        //Student
        //Person
    }
}

com/oop/demo/Person.java

package com.oop.demo;

public class Person {
    public Person() {
        System.out.println("Person无参构造");
    }
    public void print(){
        System.out.println("Person");
    }
}

com/oop/demo/Student.java

package com.oop.demo;

public class Student extends Person{
    public Student() {
        //隐藏代码:调用了父类的无参构造super();
        //super();
        System.out.println("Student无参构造");
    }
    public void print(){
        System.out.println("Student");
    }
    public void test1(){
        print();
        this.print();
        super.print();
    }
}

方法重写@Override

子类的方法和父类必须要一致,方法体不同

重写都是方法的重写,和属性无关

静态方法不能被重写 !

注意点
  1. 方法名,参数列表必须相同
  2. 修饰符范围可以扩大不能缩小
  3. 抛出异常范围可以缩小不能扩大
代码示例

静态方法

public class B {
    public static void test(){
        System.out.println("B=>test()");
    }
}
public class A extends B{
    public static void test(){
        System.out.println("A=>test()");
    }
}
public class Application {
    public static void main(String[] args) {
        //静态方法:方法调用只和左边定义的数据类型有关
        A a = new A();
        a.test();//A=>test()
        //父类的引用指向了子类
        B b = new A();
        b.test();//B=>test()
    }
}

方法重写

public class B {
    public void test(){
        System.out.println("B=>test()");
    }
}
public class A extends B{
    @Override
    public void test() {
        System.out.println("A=>test()");
    }
}
public class Application {
    public static void main(String[] args) {
        A a = new A();
        a.test();//A=>test()
        B b = new A();
        b.test();//A=>test()
    }
}

多态

同一方法根据发送对象不同,采用多种不同的行为方式;

一个对象的类型是确定的,但可以指向对象的引用类型有很多(可以是子类,父类,Object)

多态存在的条件:

  1. 有继承关系
  2. 子类重写父类方法
  3. 父类引用指向子类对象

注:多态是方法的多态,属性没有多态。

无法重写的方法
  1. static方法,属于类,不属于实例
  2. final 常量 (final修饰的类不能被继承)
  3. private方法
//子类能调用的方法都是自己的或继承父类的
A a = new A();
B b = new B();
//对象能执行哪些方法看左边的引用类型
//父类引用可以指向子类,但不能调用子类独有的方法
B c = new A();
a.test();//A=>test()
b.test();//B=>test()
//子类重写了父类方法,会执行子类的方法
c.test();//A=>test()

instanceof和类型转化

  1. 父类引用可以指向子类的对象,反过来不行
  2. 子类转换为父类称为向上转型,可能丢失自己本来的一些方法
  3. 父类转换为子类称为向下转型,需要强制转换
public class Application {
    public static void main(String[] args) {
        //子类特有方法go
        Student s = new Student();
        s.go();
        //向上转型,转型后无法再调用go方法
        Person p = s;
        //向下转型
        ((Student) p).go();
    }
}

static关键字

静态变量
private static int age;
静态方法
public class Application {
    private static void test(){
        System.out.println("Static Function");
    }
    public static void main(String[] args) {
        test();
    }
}
静态代码块
public class Person {
    {
        System.out.println("匿名代码块");
    }
    static {
        System.out.println("静态代码块");//只会在类加载时执行一次
    }
    public Person() {
        System.out.println("构造方法");
    }
    public static void main(String[] args) {
        Person p = new Person();
        //静态代码块
        //匿名代码块
        //构造方法
    }
}
静态导入包
import static java.lang.Math.random;
public class Person {
    public static void main(String[] args) {
        System.out.println(random());
    }
}

抽象类 abstract

//抽象类 (接口可以多继承)
abstract class Person {
    public abstract void doSomething();//抽象方法:只有方法名,没有方法体
}

注:

  1. 抽象类不能new,只能靠子类实现
  2. 抽象方法必须在抽象类中,但抽象类可以包含普通方法

接口 interface

对对象的抽象,约束和实现分离:面向接口编程

注:

  1. 接口不能被实例化,接口中没有构造方法
  2. 接口中所有方法都是抽象的(public abstract)
  3. 接口中只有常量(public static final)
  4. 类通过implements实现接口,一个类可以实现多个接口,实现多继承
  5. 实现接口的类,必须重写接口中所有方法
public interface UserService {
    void userTest1();
    void userTest2();
}
public interface TimeService {
    void time1();
    void time2();
}
public class UserTime implements UserService,TimeService{
    @Override
    public void userTest1() {
    }
    @Override
    public void userTest2() {
    }
    @Override
    public void time1() {
    }
    @Override
    public void time2() {
    }
}

内部类

匿名对象:不将实例保存到变量(栈)中,只在堆内存中使用对象

public class Application {
    public static void main(String[] args) {
        new Apple().eat();
    }
}
class Apple{
    public void eat(){
        System.out.println("吃苹果");
    }
}

匿名内部类

public interface UserService {
    void userTest1();
    void userTest2();
}
public class Application {
    UserService u = new UserService() {
        @Override
        public void userTest1() {
        }
        @Override
        public void userTest2() {
        }
    };
}

异常Error Exception

Error

Error类对象由JVM生成并抛出,大多数错误与操作无关,发生错误时JVM一般会终止线程;

如内存溢出(OutOfMemeryError),栈溢出,类定义错误(NoClassDefFoundError),链接错误(LinkageError)

Exception

异常通常由逻辑错误引起,应尽量避免
  1. 非运行时异常(IO异常...)
  2. 运行时异常(RuntimeException)

注:Error通常是致命性错误,程序无法处理;Exception通常可以且应该尽可能的处理。

异常处理机制

  1. try 监控区域 (必要)
  2. catch 捕获异常 (必要)
  3. finally 最终处理 (释放占用资源)
  4. throw 抛出异常(一般在方法中使用 )
  5. throws

注:捕获多个异常需要从小到大XXXException < XXXException < Throwable

public class Application {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;
        try{
            if(b == 0){
                throw new ArithmeticException();
            }
            System.out.println(a/b);
        }catch (ArithmeticException e){
            e.printStackTrace();//打印错误的栈信息
        }catch (Exception e){
            
        }catch (Throwable e){
            
        }finally {
            
        }
    }
}

自定义异常

用户自定义异常类,只需要继承Exception类即可
public class MyException extends Exception {
    String msg;

    public MyException(String msg) {
        this.msg = msg;
    }

    @Override
    public String toString() {
        return "MyException{" + msg + "}";
    }
}
public class Application {
    static void test(String msg) throws MyException{
        throw new MyException(msg);
    }
    public static void main(String[] args) {
        try{
            test("test");
        }catch (MyException e){
            System.out.println(e);//MyException{test}
        }
    }
}

你可能感兴趣的:(javajava-se)