软工Java学习

JAVA

第一章 JAVA基础

1.jdk jre jvm

image

JDK: Java标准开发包。提供了编译、运行Java程序所需的各种工具和资源,包括Java编译器、Java运行时环境,以及常用的Java类库等。

JRE: Java运行环境,用于解释执行Java的字节码文件。

JVM: Java虚拟机,是JRE的一部分。负责解释执行字节码文件,是可运行Java字节码文件的虚拟计算机

区别联系: JDK包含JRE,JDK和JRE中都包含JVM。JDK除了包含JRE,还包含一些常用开发工具和基础类库。JDK用于开发Java程序,JRE用于运行Java程序。JVM是Java编程语言的核心,并且具有平台独立性。

2.开发Java程序需要的三个步骤

  1. 编写源程序
  2. 编译源文件生成字节码文件
  3. 加载运行字节码文件

3.Java程序运行过程

javac a.java    //编译.java源文件生成.class字节码文件
java a.class    //运行java文件

4.Java程序语句执行顺序

顺序结构、选择结构、循环结构、异常处理逻辑结构

第二章 编程基础

1.Java的基本语法

方法格式:

权限修饰符 返回值类型 方法名(参数列表){
    方法内容;
    return 返回值;
}
public int sum(int a,int b){
    int sum=a+b;
    return sum;
}

权限修饰符:

类内部 本包 子类 外部包
public
protected ×
default × ×
private × × ×

一个包里面只能有一个公共类(public)。default又叫友好型

注释:// /* */ /** **/

关键字: 被占用的名称。

2.变量的数据类型

变量的定义:

按所属的数据类型划分:基本数据类型变量、引用数据类型变量

按被声明的位置划分:局部变量、成员变量

内存图:

image

变量的类型转换:

boolean​类型不能转换成任何其他数据类型。

自动类型转换:容量小的类型自动转换成容量大的数据类型 byte,short,int -> float -> long -> double

byte,short,int​不会相互转换。他们三者在计算时会转换成int​类型

强制类型转换:容量大的类型转换成容量小的类型时,要用强制类型转换符 a = (int)b;

变量的作用域:

成员变量:在方法外,类内定义的变量。在整个类里起作用。

局部变量:在方法里定义的变量。只在方法里起作用。

常量:

final int a;

注意事项:

float a= 4.2f;  //4.2默认为double类型,如果不加f,会报错
long a = 222222222222l; //带上l
char c = 's'; //带上''

3.运算符

算术:+ - * / % ++ --

赋值:=

关系运算符:> < >= <= == !=

逻辑:! && ||

位运算符:>> << $ | ~ ^

条件运算符: 三目运算符XX?X:X

4.选择和循环

if(a&gt;0){
}else if(a&lt;0){
}else{
}
switch(a){
    case 1: //当a==1时
    //执行内容
    break;
    case 2: //当a==2时
    break;
    default:    //当a==其他的时候
    break;
}
for(int i=0; i&lt;10; i++){
}
while(i&lt;10){
}
do{
}while(i&lt;10)
/*
* for( 总的的每一个元素的数据类型 别名:要遍历的、总的 ){
*     操作这个别名
* }
*/
int a[] = new int[]{1,2,3,4,5,6,7};
for(int a1 : a){
    a1 = a1+10;
}

5.数组

多维数组初始化: 没有赋值时,值默认为0

//动态声明01
int[][] arr = new int[3][];
arr[0] = new int[3];    //第0行有三列
arr[1] = new int[2];    //第1行有两列
arr[2] = new int[1];    //第2行有一列

//动态声明02
int [][] arr2 = new int[3][2];
arr2[0][0]=33;  //第0行0列为33

//静态声明01
int arr3[][] = new int[][]{{1,2,3},{2,3}};

数组的常见操作:

//声明数组
int arr[];

//数组初始化
int a[] = new int[]{2,1,3};
int a1[] = new int[3];

//查看数组长度
a.length;

//for each遍历
for(int m:a){
   m=m+1;
}

//数组的拷贝
int b[]=a;
int b1[] = Arrays.copyOf(a,2);
// int arr2[] = Arrays.copyOf(arr,自定义长度);

//数组排序
Arrays.sort(a); //从小到大排序

//将int数组转换为字符串
Arrays.toString(a);

6.输入输出

输入:

Scanner s = new Scanner(System.in);
String next = s.next();
int i = s.nextInt();
float v = s.nextFloat();

输出:

System.out.println(&quot;输出&quot;); //ln表示换行
System.out.print(&quot;输出&quot;);   //不会换行
System.out.printf(&quot;输出i为:%d&quot;, i);  //不会换行

7.类与对象

三大特征:

  1. 封装: 通过访问控制关键字实现属性或方法的封装,仅对外提供公共访问方式。
    封装的好处:实现对数据项和方法的隐藏;实现隐藏隔离,允许外部对类做有限的访问,开发者可以自由的改变类的内部实现;提高了代码的重用性
  2. 继承: 通过extends​实现继承。
    两个好处:代码重用;通过继承实现对现实世界更准确的建模
  3. 多态: 一个对象变量可以指向多种实际类型对象的现象被称为“多态”。
    三个必要条件:继承、方法的重写、父类引用指向子类对象
    多态的好处:提高了代码的维护性(继承保证);提高了代码的扩展性
    Java中多态的实现方式:接口实现,继承父类进行方法重写,同一个类中进行方法重载。父类引用指向子类对象

实例化对象(对象的创建):

Student stu = new Student();

类的定义:

[修饰符] class 类名 [extends 父类名] [implements 接口名]{  //中括号里的,可有可无
    // 类体,包括类的成员变量和方法
    /* 具体方法如下:
    *  1.get.set方法
    *  2.构造函数:包括一个全参的构造函数和一个无参的构造函数
    *  3.自定义的函数函数
    */ 
}

8.继承

object类: object类是所有类的父类,里面有很多方法

类的继承格式:

public class Child extends Parent{

}

子类有父类非私有(​private​)的方法和成员变量

重写父类方法:

public class Child extends Parent{
    public void myParent(){
    System.out.println(&quot;我是子类的重写&quot;);
    }
}

9.类的封装

为什么要进行封装: 将类的某些信息隐藏在类的内部,不允许外部程序直接访问。而是通过该类提供getter/setter​的方法来对隐藏的信息进行操作和访问

封装的实现步骤:

  1. 修改属性的可见性,将其设为private
  2. 创建getter/setter​方法(用于属性的读写)
  3. getter/setter​方法中加入属性控制语句(对属性的合法性进行判断)
public class Person {
    private int age;
    private String name;
    public String getName(){
        return name;
    }
    public int getAge(){
        return age;
    }
    public void setAge(int age){
        if(age &lt;0){
            System.out.println(&quot;age不合法,请重新输入&quot;);
        }else {
            this.age = age;
        }
    }
    public void setName(String name){
        this.name = name;
    }

}

class Test2{
    public static void main(String[] age){
        Person person = new Person();
        person.setAge(60);
        person.setName(&quot;hello&quot;);
        System.out.println(person.getAge());
        System.out.println(person.getName());
    }
}

10.构造方法

定义: 在创建对象时初始化对象,即为对象成员变量赋初始值,总与new一起在创建对象的语句中使用,一个类可以有多个构造函数。可根据其参数个数的不同或参数类型的不同来区分他们。

public class Person {
    private int age;
    private String name;

    public Person(){

    }
    public Person(String name){
        this.name = name;
    }
    public Person(int age){
        this.age = age;
    }
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }
    public String getName(){
        return name;
    }
    public int getAge(){
        return age;
    }
    public void setAge(int age){
        if(age &lt;0){
            System.out.println(&quot;age不合法,请重新输入&quot;);
        }else {
            this.age = age;
        }
    }
    public void setName(String name){
        this.name = name;
    }

}

class Test2{
    public static void main(String[] age){
        Person person = new Person(&quot;hello&quot;, 60);
        System.out.println(person.getAge());
        System.out.println(person.getName());
    }
}

11.方法的重载与重写

重载的概念:

  1. 必须在同一个类中
  2. 方法名相同
  3. 方法的参数的个数、顺序或类型不同
  4. 与方法的修饰符或返回值没有关系
public class Person {
    public void myPrint(){
        System.out.println(&quot;我是重载方法1&quot;);
    }
    public int myPrint(String name){
        System.out.println(&quot;我是重载方法2&quot;);
        return 1;
    }
    public int myPrint(int age){
        System.out.println(&quot;我是重载方法3&quot;);
        return 1;
    }
}

重写的概念: 当父类中的方法无法满足子类需求的时候,需要方法重写

方法重写的注意事项:

  1. 重写的方法必须要和父类一模一样
  2. 重写的方法可以使用@Override​注解来标识
  3. 子类中重写的方法的访问权限不能低于父类中方法的访问权限:private < 默认 < protected < public
public class Parent {
    protected void myPrint(){
        System.out.println(&quot;Parent&quot;);
    }
}

class Son extends Parent{
    @Override
    public void myPrint(){
        System.out.println(&quot;son&quot;);
    }
}

class Test{
    public static void main(String[] args) {
        Son son = new Son();
        son.myPrint();
    }
}

重写重载的区别

重载:在同一个类中,出现多个同名的方法,参数列表不同,与返回值类型,修饰符无关

重写:子类中出现和父类中一模一样的方法(包括返回值类型,方法名,参数列表),子类中的访问修饰符大于等于父类的访问修饰符。

12.this/super关键字

this关键字: Java中,为解决变量的命名冲突和不确定性问题而引入this​关键字,this​代表对当前对象的引用

用法:

image

注意:this​只能在非静态类中使用,静态方法和静态的代码块中绝对不能出现this。原因static​方法在类加载时就已经存在了,但是对象是在创建时才在内存中生成的。

super关键字: super关键字主要存在于子类方法中,用于指向父类对象。可以访问父类的属性、函数以及构造函数。

用法:

  1. 子类父类中存在同名成员时(包括变量和方法),在子类中默认是访问子类的成员,可通过super关键字指定访问父类的成员。
  2. 默认会先调用父类无参的构造方法,可通过super关键字指定调用父类的构造方法。

13.static/final关键字

static关键字: 被static修饰的变量属于类变量/方法,可以通过类名、变量名/方法名直接引用,而不需要new一个累出来。

final关键字: final修饰的类不能被继承。final修饰的方法不能被重写,但是可以被使用。修饰的变量就不能再改变了。

14.抽象类

15.接口

image

接口和抽象类的区别:

image

16.多态

继承是多态的前提。(继承包括extends​和implements​)

父类引用指向子类对象:Father father = new Son();

public class Parent {
    private  String name = &quot;hello&quot;;
    protected void myPrint(){
        System.out.println(&quot;Parent&quot;);
    }

    protected void parentPrint(){
        System.out.println(&quot;Parent&quot;);
    }
}

class Son extends Parent{
    @Override
    protected void myPrint(){
        System.out.println(&quot;Son&quot;);
    }
}

class Test{
    public static void main(String[] args) {
        //多态写法:左侧父类的引用指向右侧的子类
        //子类父类都有,输出子类的;子类没有,往上找
        Parent obj = new Son();
        obj.myPrint();
        obj.parentPrint();
    }
}

17.异常

image

Throwable​​类是所有错误与异常的父类,只有该类型的对象才能被throw​​抛出,它有两个子类:

  1. Error​​:灾难性错误
  2. Exception​:表示异常,是可以解决的问题。有一个子类叫RuntimeException​,是java程序运行过程中出现的问题,是运行期异常。

RuntimeException: 以下是一些常见的RuntimeException​及其子类异常:

  1. ArrayIndexOutOfBoundsException​(数组索引越界异常):当尝试访问数组中不存在的索引时抛出。
  2. IllegalArgumentException​(非法参数异常):当传递给方法的参数不合法或无效时抛出。
  3. IllegalStateException​(非法状态异常):当对象的状态不适合执行特定操作时抛出。
  4. ArithmeticException​(算术异常):当发生算术错误,例如除以零时抛出。
  5. NumberFormatException​(数字格式异常):当字符串无法转换为数字类型时抛出。

异常处理的作用: 对方法传递过来的参数进行合法性效验。如果参数不合法,就用抛出异常的方式告知方法的调用者,传递的参数有问题。

throw关键字的作用: throw关键字可以在指定的方法中抛出指定的异常

使用格式:throw new xxxException("异常产生的原因");

if(arr == null){
    throw new NullPointerException(&quot;传递的数组的值是null&quot;);
}

注意:

  1. throw关键字必须写在方法的内部
  2. throw关键字后边new的对象必须是Exception或Exception的子类对象。
  3. throw关键字抛出异常后,我们就必须处理这个异常对象:
    创建的是RuntimeException​或RuntimeException​子类的对象,我们可以不处理,默认交给JVM处理
    创建的是编译异常,我们就必须处理这个异常,要么throws要么try-catch处理

使用throws抛出异常: 异常处理的第一种方法----交给调用者处理,最终交给JVM处理(中断处理)

使用格式:

/*
    修饰符 返回值 方法名(参数列表) throws AAAException,BBBException{
    throws new AAAExcpeiton(&quot;产生原因&quot;);
    throws new BBBExcpeiton(&quot;产生原因&quot;);
    }
*/
public static void readFile(String fileName) throws FileNotFoundException{
   if(! fileName.equals(&quot;c:\\\\a.txt&quot;)){
    throw new FileNotFoundException(&quot;传递路径错误&quot;);    //编译异常
    }
}

注意:

  1. throws关键字必须写在方法声明处
  2. throws关键字后面声明的异常必须是Exception或Exception的子类
  3. 方法内部如果抛出了多个异常,那么throws后边也必须声明多个异常
    如果抛出的多个异常对象有子父类关系,那么直接声明父类异常即可
  4. 调用了一个声明抛出异常的方法,我们就必须处理声明的异常:
    要么继续使用throws声明抛出异常,最终交给JVM处理;要么try-catch自己处理异常

使用try-catch-finally处理异常: 异常处理的第二种方式----自己处理异常

使用格式:

/*
    try{
        可能产生异常的代码
    }catch(定义一个异常变量,用来接收try重抛出的异常对象){
        异常的处理逻辑,接收异常对象后怎么处理异常对象
        一般会把异常的信息记录到一个日志中
    }
    ...
    catch(异常类名 变量名){

    }finally{
    }
*/
public static void main(String[] args){
    try{
    readFile(&quot;d:\\a.tx&quot;);
    }catch(FileNotFoundException e){
    System.out.println(&quot;文件路径错误&quot;);
    }
    System.out.println(&quot;后续代码&quot;);
}

public static void readFile(String fileName) throws FileNotFoundException{
   if(! fileName.equals(&quot;c:\\\\a.txt&quot;)){
    throw new FileNotFoundException(&quot;传递路径错误&quot;);    //编译异常
    }
}

注意:

  1. try中可能会抛出多个异常对象,那么就可以使用多个catch来处理这些异常对象
  2. 如果try中产生了异常,那么就会执行catch中的异常处理逻辑,执行完毕catch中的处理逻辑后执行finally块,然后继续执行后续代码
    如果try中没有产生异常,那么就不会执行catch中的异常处理逻辑,执行完try中的代码后执行finally块,继续执行后续代码
  3. finally块必须执行,与异常是否抛出无关
  4. 多个catch块会按照从上往下的顺序进行匹配,当匹配到某个catch块时,就会进入到这个catch块中而忽略掉后续的所有catch块(只进入一个catch)

自定义异常类: Java提供的异常类不够使用时,需要自己定义一些异常类

格式:

/*
    public class XXXException extends Exception | RuntimeException{
        添加一个空参数的构造方法
        添加一个异常信息的构造方法
    }
*/
public class RegisterException extends Exception{
    //空参数的构造方法
    public RegisterException(){
    super();
    }
    //带异常信息的构造方法
    public RegisterException(String message){
    super(message);
    }
}

注意:

  1. 自定义异常类一般都是以Exception结尾,说明该类是一个异常类
  2. 自定义异常类,必须继承Exception或者RuntimeException
    继承Exception:自定义异常类就是一个编译期异常,必须处理,要么throws要么try-catch
    继承RuntimeException:自定义异常类就是一个运行期异常,可以不处理交给JVM处理(中断处理)

18.多线程

继承Thread创建多线程:java.lang.Thread​是描述线程的类,我们想要实现多线程程序,就必须继承Thread类

Java程序属于抢占式调度,哪个线程的优先级高,哪个线程就先执行;同一优先级,随机选择一个执行

实现步骤:

  1. 创建一个Thread类的子类
  2. 在Thread类的子类中重写Thread类中的run方法,设置线程任务(开启线程要做什么?)
  3. 创建Thread类的子类对象
  4. 调用Thread类中的方法start方法,开启新线程,执行run方法
    void start():使该线程开始执行;JVM调用该线程的run方法。
    结果是两个线程并发地运行;当前线程(main线程)和另一个线程(执行其run方法)。
    多次启动一个线程是非法的,特别是当前线程已经结束执行后不能再重新启动。
//1.创建一个Thread类的子类
public class MyThread extends Thread{
    @Override
    //2.在Thread类的子类中重写Thread类中的run方法,设置线程任务
    public void run(){
    for(int i = 0; i&lt;20; i++){
        System.out.println(&quot;run:&quot;,i);
    }
    }
}

class test{
    public static void main(String[] args){
    //3.创建Thread类的子类对象
    MyThread mt = new MyThread();
    //4.调用Thread类中的方法start方法,开启新线程,执行run方法
    mt.start();

    for(int i = 0; i&lt;20; i++){
        System.out.println(&quot;main:&quot;,i);
    }
    }
}

实现Runnable接口实现多线程的实现步骤:

  1. 创建一个Runnable接口的实现类
  2. 在实现类中重写Runnable接口的run方法,设置线程任务
  3. 创建一个Runnable接口的视线对象
  4. 创建Thread类对象,构造方法中传递Runnable接口的实现类对象
  5. 调用Thread类中的start方法,开启新线程调用run方法
//1.创建一个Runnable接口的实现类
public class RunnableImpl implements Runnable{
    //2.在实现类中重写Runnable接口的run方法,设置线程任务
    @Override
    public void run(){
    for(int i=0; i&lt;10; i++){
        System.out.println(Thread.currentThread().getName()+&quot;--&gt;&quot;+i);
    }
    }
}

class test{
    public static void main(String[] args){
    //3.创建一个Runnable接口的视线对象
    RunnableImpl run = new RunnableImpl();
    //4.创建Thread类对象,构造方法中传递Runnable接口的实现类对象
    Thread t = new Thread(run);
    //5.调用Thread类中的start方法,开启新线程调用run方法
    t.start();

    for(int i = 0; i&lt;20; i++){
        System.out.println(&quot;main:&quot;,i);
    }
    }
}

同步代码块:synchronized

格式:

/*
    synchronized(锁对象){
        可能会出现线程安全问题的代码
    }
*/
public class RunnableImpl implements Runnable{
    //定义一个多线程共享的票源
    public int ticket = 100;

    //创建锁对象
    Object obj = new Object();

    //设置线程任务:买票
    @Override
    public void run(){
    while(true){
        //同步代码块
        synchronized(obj){
        if(ticket&gt;0){
            //提高安全问题出现概率
            try{
            Thread.sleep(10);
            } catch(InterruptedException e){
            e.printStackTrece();
            }

            System.out.println(Thread.currentThread().getName()+&quot;--&gt;正在卖第&quot;+ticket+&quot;张票&quot;);
            ticket--;
        }
        }
    }
    }
}

注意:

  1. 通过代码块中的锁对象,可以使用任意的对象
  2. 但是必须保证多个线程中使用的锁对象是同一个
  3. 锁对象作用:把同步代码块锁住,只让一个线程在同步代码中执行

线程之间的通信:wait/notify​。调用wait方法会放弃cpu的执行,进入到WAITING状态(无限等待);调用notify方法来唤醒,会继续执行wait之后的代码。必须保证wait和notify同时只有一个在执行。同步使用的锁对象必须保证唯一,且只有锁对象才能调用wait和notify。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇