JavaSE学习笔记(学自狂神视频)

一、杂项
基础
  • 局部变量 只在方法里有用,要初始值

  • switch只能用int byte short char

  • 变成包的样子在包里面,要在最开头写,package 路径;如(package com.sun.base;)

    要在一个包的类里面用到别的包的类,需要导包,import 路径;如(import com.sun.operator.Hello;)

    若,需要用到此包中所有类,就直接用号,如(import com.sun.operator.

  • JavaDoc的注释方法可以生成一个说明文件,详细介绍这个Java文件

  • 可变长参数:……要在最后。

  • 单引号中的英文是int,双引号是String。

  • 类变量 方法里面就不用new一个东西再使用,可以像局部变量一样直接用。

    实例变量 就要new一个东西再用sout(东西.变量)来输出。

  • 一个Java类中可以有多个class类,但是只能有一个public

  • Java语言是以类为程序的基本单位

  • 命令行运行包里面的类,要回退到包的那个文件夹,然后用包路径com.xxx.xxx.xxx去运行。构建不用。

  • 用static修饰符修饰的方法是属于整个类的类方法,调用时,使用类名作为前缀。不用static的是属于某个具体类对象或实例的方法,调用时,使用具体的对象名作为前缀。

    static是最早出生的,如果要调用一个不是static的就拿不到,因为还没生出来。

  • 内部类可以使用外部类的私有属性。

//定义一个函数式接口(只有一个方法的接口)
interface I_Like{
    void Like();
}

//1、常见
class Like1 implements I_Like{
    @Override
    public void Like() {
        System.out.println("I like1 you");
    }
}

public class 多种类的对比 {
    //2、静态内部类
    static class Like2 implements I_Like{
        @Override
        public void Like() {
            System.out.println("I like2 you");
        }
    }


    public static void main(String[] args){
        //定义接口对象
        I_Like like;
        //3、局部内部类
        class Like3 implements I_Like{
            @Override
            public void Like() {
                System.out.println("I like3 you");
            }
        }


        like = new Like1();
        like.Like();

        like = new Like2();
        like.Like();

        like = new Like3();
        like.Like();
        //4、匿名内部类,没有类的名称,需要借助接口或父类
        like = new I_Like(){
            @Override
            public void Like() {
                System.out.println("I like4 you");
            }
        };
        like.Like();
        //5、lambda形式
        like=()->System.out.println("I like5 you");
        like.Like();
    }


}

File类的一些方法

canRead() 文件是否可读

length() 文件长度

getAbsolutePath() 文件绝对路径

数组

动态初始化数组的格式:数组类型[] 数组名称 = new 数组类型 [数组长度];

静态初始化数组:数组类型[] 数组名称 = new 数组类型 []{};

左侧数据类型:表示数组中保存的数据是什么类型;

左侧中括号:代表是一个数组;

右侧数据类型:与左侧相同;

右侧中括号:表示数组中可以保存多少数据;

二维的在后面再加个中括号就行

a.length是第几行,a[].length是第几行有多少数。

二、方法
  • 方法重载,定义一样的方法,一个int的和一个double的,根据输入的数据会自动使用相应类型的方法。

  • 方法重写,在子父类间,将父类一样的方法重新去编写。

  • 私有变量/方法:同一个包里面的不同类不能调用。

    友好变量/方法:同一个包里面的不同类都可以调用。

    public>protected>友好的>private

  • 封装就是使用private去定义变量,通过方法get/set去调用。参考书本的92页。

  • static方法只能处理static数据

    当需要引用或修改一个static限定的类属性时,可以使用类名也可以使用对象名。(访问的是同一个内存单元)

  • new对象后面的(),没东西就是无参构造方法。

子类不继承父类的构造方法,如果子类构造方法中没有指明调用哪一个父类构造方法,将会自动调用父类无参构造,如果要使用有参需要在super的括号中写入参数名。

多态
  • 多态是方法的多态,属性没有多态。
  • 存在的条件:继承关系、方法重写、父类引用指向子类对象 Father f1 = new Son();
  • static/final/private没有多态。
对象的继承

对象instanceof类,如果这个对象是这个类或者它的子类创造的,就可以得到true。

对象的上转型对象:

Animal a;(Animal类是Tiger类的父类)

a = new Tiger();(称a是b的上转型对象)

1.上转型对象不能操作子类新增的东西。(所以要加上子类名字并括号,类似强制转换。)

2.上转型对象调用的只会是子类没重写的或者重写后的。

抽象类

1.抽象类不能new,只能靠子类去实现。

2.抽象方法是没有方法内容的,只有声明。

3.抽象方法必须在抽象类里,抽象类不一定有抽象方法。

4.子类重写父类的抽象方法。

接口

1.定义一些方法,让不同的人实现。

2.默认方法前缀public abstract

3.默认常量前缀public static final

4.接口不能被实例化,接口中没有构造方法

5.implements可以实现多个接口

6.抽象类可以不重写直接用。

7.接口与存储空间无关,因为不包含任何实现。

抽象类中的非抽象方法不用重写,其他必须重写,接口的方法必须重写,接口和抽象类中只有方法名,没有定义的,如果你不定义 也就是空方法,接口就是为了弥补java不能多重继承,接口针对的是对象而不是实现。实现的部分可以交由对象去实现。这就是java中的多态啊。好好思考一下上面的几句话就行了。一定要对java的基本理论清楚。

接口回调类似上转型对象。

匿名

使用一般形式传参:

Scanner sc = new Scanner(System.in);

int num = sc.nextInt();

使用匿名对象传参:

int num = new Scanner(System.in).next.Int();

System.out.println(“输入的是:”+num)

1.匿名的是只用一次的,所以直接new。

异常

异常的捕获是层层递进的,如果在上面已经捕获了一个大的异常,那么下方无法捕获大异常内的小异常。并且,不要用子类去捕获父类的异常,尽量用一个父类去捕获所有子类的异常。

Label类即创建一个标签,用于显示一些不需要修改的文本信息。

actionListener接口监听和处理TextFiled对象的事件

在这里插入图片描述
在这里插入图片描述

根据程序的构成和运行环境的不同,Java源程序分为两大类:Application程序和Applet程序。

GUI

JLabel 标签,显示在最底层的文字

JButton按钮

JPanel面板,把组件加进去

多线程

自定义一个类,作为线程类继承Thread类,用于创建线程。

重写run()方法,run()是线程的执行体。

创建线程对象后,调用自带的start()方法启动线程,观察多线程机制。

注意点

在这里插入图片描述

new了Thread就等于是一个新线程了,race只是一个对象,一个平台,去运行线程。

两种多线程方式

不涉及多个线程操作一个对象就可以只Thread

继承Thread类

  • 子类继承,所以具备多线程能力
  • 启动线程:子类对象.start()
  • 不建议使用:因为要避免OOP单继承局限性
public class TestThread1 extends Thread{
    @Override
    public void run() {
        //run方法线程体
        for(int i=0;i<20;i++){
            System.out.println("我在看片--"+i);
        }
    }

    public static void main(String[] args){
        //主线程

        //创建线程
        TestThread1 t1 =new TestThread1();

        //开始线程
        t1.start();

        for(int i =0;i<2000;i++) {
            System.out.println("我在听歌--"+i);
        }
    }
}

实现Runable接口

  • 实现接口Runable,使具有多线程能力
  • 启动线程:传入目标对象+Thread对象.start()
  • 推荐使用:因为它灵活,方便同一个对象被多个线程使用
package com.sun.多线程;

public class TestThread2 implements Runnable{
    @Override
    public void run() {
        //run方法线程体
        for(int i = 0;i < 20; i++){
            System.out.println("我在看片--"+i);
        }
    }

    public static void main(String[] args){
        //主线程

        //创建线程
        TestThread2 t1 = new TestThread2();

        //开始线程
        new Thread(t1).start();

        for(int i=0;i<2000;i++){
            System.out.println("我在听歌--"+i);
        }
    }
}

在这里插入图片描述

并发问题

多个线程操作同一个资源可能引发线程不安全,数据紊乱。

线程休眠sleep
  • sleep(time)指当前吸纳成阻塞的毫秒数。
  • sleep存在异常interrupedException。
  • sleep时间到了之后,线程进入就绪状态。
  • sleep可以模拟网络延时,倒计时等等。
  • 每一个对象都有一个锁,sleep不会释放锁。
  • sleep可以放大问题的发生性
线程礼让yield
  • 礼让线程,让当前正在执行的线程暂停,但不阻塞。
  • 讲线程从运行状态转为就绪状态。
  • cpu重新调度,但是让不让还是看cpu看谁顺眼。
线程强制执行join
  • join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞
  • 类似插队
线程五大态
  • NEW

    尚未启动的线程

  • RUNNABLE

    在JVM里执行的线程

  • BLOCKED

    被阻塞等待监视器锁定的线程

  • WAITING

    正在等待另一个线程执行操作的线程

  • TIMED_WAITING

    正在等待另一个线程执行操作到了一定时间的线程

  • TERMINATED

    已经退出(死翘翘)的线程

优先级

通过getPriority()获取当前优先级

通过setPriority(int xx)改变当前优先级

守护线程

setDaemon(ture)通过这个方法将他定义为守护线程。

线程同步方法

synchronized

两种使用方式,一种是在方法声明里加入synchronized

class BuyTicket implements Runnable{
	public void buy(){
    	xxx.xxx;
	}
}
//变为
class BuyTicket implements Runnable{
	public synchronized void buy(){
    	xxx.xxx;
	}
}

但是在方法中直接插入synchronized字段的方式不可取,因为synchronized锁定的线程是他所在的对象,

如上例,锁定的是class BuyTicket{}

第二种方式

synchronized(obj){}

//同步前。

package com.sun.多线程;

public class BankDrawing {
    public static void main(String[] args) {
        Account account = new Account(1000,"钱");

        Drawing I = new Drawing(account,800,"我");
        Drawing you = new Drawing(account,600,"你");


        you.start();
        I.start();
        

    }
}

class Account {
    int money;
    String name;

    public Account(int money, String name){
        this.money = money;
        this.name = name;
    }
}

class Drawing extends Thread{
    Account account;//账户
    String name;
    int drawingMoney;//取钱
    int nowMoney;//手里的钱

    public Drawing(Account account, int drawingMoney, String name){
        super(name);
        this.account = account;
        this.drawingMoney =drawingMoney;
    }

    @Override
    public void run(){

        //判断有没有钱
        if(account.money-drawingMoney<0){
            System.out.println(Thread.currentThread().getName()+"钱不够,取不了");
            return;
        }
        account.money = account.money-drawingMoney;
        nowMoney = nowMoney+drawingMoney;
        System.out.println(Thread.currentThread().getName()+"取了"+drawingMoney);
        System.out.println("卡里还剩"+account.money);
        System.out.println(Thread.currentThread().getName()+"手里有"+nowMoney);
    }
}

//同步后。

package com.sun.多线程;

public class BankDrawing {
    public static void main(String[] args) {
        Account account = new Account(1000,"钱");

        Drawing I = new Drawing(account,800,"我");
        Drawing you = new Drawing(account,600,"你");


        you.start();
        I.start();
        

    }
}

class Account {
    int money;
    String name;

    public Account(int money, String name){
        this.money = money;
        this.name = name;
    }
}

class Drawing extends Thread{
    Account account;//账户
    String name;
    int drawingMoney;//取钱
    int nowMoney;//手里的钱

    public Drawing(Account account, int drawingMoney, String name){
        super(name);
        this.account = account;
        this.drawingMoney =drawingMoney;
    }

    @Override
    public void run(){

        synchronized(account){
            //判断有没有钱
            if(account.money-drawingMoney<0){
                System.out.println(Thread.currentThread().getName()+"钱不够,取不了");
                return;
            }
            account.money = account.money-drawingMoney;
            nowMoney = nowMoney+drawingMoney;
            System.out.println(Thread.currentThread().getName()+"取了"+drawingMoney);
            System.out.println("卡里还剩"+account.money);
            System.out.println(Thread.currentThread().getName()+"手里有"+nowMoney);
        }
    }
}

使用synchronized(obj){}将代码块包裹住,让他不会作用于本身。

lock锁

lock锁只能锁代码块。而且需要手动开启和关闭锁(即.lock和.unlock)

与synchronized不同之处在于,synchronized是隐式的,而且可以锁方法,并且自动释放。

class X{
    //通过ReentrantLock定义锁对象
    private final ReentrantLock lock=new ReentrantLock();
     
    //定义需要保证线程安全的方法
    public void m() {
        //加锁
        lock.lock();
        try {
            //需要保证线程安全的代码
        }
        finally {
            //关闭/释放
            lock.unlock();
        }
    }
}
线程通信
  1. wait(), 表示线程一直等待,直到其他线程通知,与sleep不同,会释放锁。
  2. notify() ,唤醒一个处于等待状态的线程
  3. notifyAll(), 唤醒同一个对象上所有调用wait()方法的线程,优先级高的线程优先调度
管程法

采用并发协作模型。

//管程法解决生产者消费者问题
public class TestPC {
    public static void main(String[] args) {
        SynContainer container = new SynContainer();

        new Productor(container).start();
        new Consumer(container).start();
    }
}

//生产者
class Productor extends Thread{
    SynContainer container;

    public Productor(SynContainer container) {
        this.container = container;
    }

    //生产
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            container.push(new Chicken(i));
            System.out.println("生产了"+i+"只鸡");
        }
    }
}

//消费者
class Consumer extends Thread{
    SynContainer container;

    public Consumer(SynContainer container) {
        this.container = container;
    }

    //消费
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("消费了-->"+container.pop().id+" 只鸡");
        }
    }
}

//产品对象
class Chicken{
    int id;
    public Chicken(int id) {
        this.id = id;
    }
}

//缓冲区
class SynContainer{
    //容器大小
    Chicken[] chickens = new Chicken[10];
    //容器计数器
    int count = 0;

    //生产者放入产品
    public synchronized void push(Chicken chicken) {
        //如果容器满了,需要等待消费者消费
        if(count == chickens.length) {
            //通知消费者消费,生产等待
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //没有满,需要丢入产品
        chickens[count] = chicken;
        count++;

        //通知消费者消费
        this.notifyAll();
    }

    //消费者消费产品
    public synchronized Chicken pop() {
        //判断能否消费
        if(count == 0) {
            //等待生产者生产,消费者等待
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //可以消费
        count--;
        Chicken chicken = chickens[count];

        //吃完了,通知生产者生产
        this.notifyAll();
        return chicken;
    }
}

信号量法
//生产者消费者方案2:信号灯法,标志位解决
public class TestPC2 {
    public static void main(String[] args) {
        TV tv = new TV();

        new Player(tv).start();
        new Wathcer(tv).start();
    }
}

//生产者--->演员
class Player extends Thread{
    TV tv;
    public Player(TV tv) {
        this.tv = tv;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            if(i%2==0) {
                this.tv.play("快乐大本营");
            } else {
                this.tv.play("douyin");
            }
        }
    }
}

//消费者--->观众
class Wathcer extends Thread{
    TV tv;
    public Wathcer(TV tv) {
        this.tv = tv;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            tv.watch();
        }
    }
}

//产品 ---> 节目
class TV {
    //演员表演,观众等待 T
    //观众观看,演员等待 F
    String voice; //表演的节目
    boolean flag = true;


    //表演
    public synchronized void play(String voice) {
        if(!flag) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println("演员表演了:"+voice);
        //通知观众观看
        this.notifyAll(); //通知唤醒
        this.voice = voice;
        this.flag = !this.flag;
    }

    //观看
    public synchronized void watch() {
        if(flag) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("观看了:"+voice);
        //通知演员表演
        this.notifyAll();
        this.flag = !this.flag;
    }
}
反射

在这里插入图片描述

在这里插入图片描述

JVM

img

方法区:存放类字节码、常量、静态变量
Java堆:存放对象实例
Java栈:方法执行

Java启动JVM,JVM 的类加载器根据 Java 命令的参数到指定的路径加载.class 类文件。

类文件加载到内存后,放到专门的方法区

JVM创建一个主线程执行这个类文件的main方法,压入Java栈运行。

方法里如果有static对象,那这个对象会存在Java堆里面,包括它的变量信息,而对象在Java堆里的地址存在Java栈里面

main方法里进入其他方法的时候,会再新建一个栈放入Java栈,运行结束就出栈。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值