Java笔记(2)

比较浮点数时需要小心:
由于一些小数(比如0.1)无法精确地用二进制表示,100个0.1自加可能永远不会等于10

java的值传递机制:
基本数据类型:传递数据的值
引用数据类型:传递数据的地址

构造方法私有化之后,只能在类中实例化,可以通过static方法在外部用不同对象调用唯一的实例,但堆空间中只能有一个实例

多态:父类的引用指向子类的对象
多态是运行时行为
多态对象不能调用子类特有的方法
对象的多态性只适用于方法,不适用属性

虚拟方法:多态时被子类重写的父类方法

向下转型:强制类型转换
为了使用强制类型转换时不出现异常,通常先用instantof关键字判断对象是哪个类的实例

String、Date、File、包装类中对equals()进行了重写,比较实体内容。
重写equals():比较两个对象的实体内容
{ ==?
对象类型?
属性(属性是String等类型时用equals()比较)?
}
编译器可自动生成equals()

Object 中 toString()输出jvm中地址
String、Date、File、包装类中对toString()进行了重写
重写的toString()一般返回属性
编译器可自动生成toString()

自动装箱和自动拆箱,可以直接 = 实现

接口。达到多重继承的效果
接口 interface 和 类 class 是并列的结构,多个类具有相同特征时可以用接口描述
接口定义:
JDK7及以前:只能定义全局常量和抽象方法
JDK8:还可以定义静态方法,默认方法
接口中不能定义构造器,不可以实例化
接口通过让类实现 implements 来使用
如果类覆盖了接口中所有抽象方法,就可以实例化,否则只能是抽象类
class AA extends BB implements CC,DD,EE

接口与接口之间也能继承,还可以多继承
interface CC extends AA,BB

接口具体使用体现了多态性
接口可以看作一种规范

接口中定义的静态方法只能通过 接口.方法 调用
接口中定义的默认方法可以通过 实现类的实例 调用

如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数方法,且子类未重写,优先调用父类方法

内部类:成员内部类 / 局部内部类(定义在方法、构造器、代码块内)
成员内部类作为外部类的成员,可以调用外部类的非静态方法

class Person{
    String name;
    int age;
    public void ea(){
        System.out.println("人吃饭");
    }
    class bird{
        eat();
        Person.this.eat();
    }
}

抓抛模型
抛:程序正常执行时,一旦出现异常,在异常代码处生成异常对象,并将对象抛出
抓:处理异常的两种方式

异常处理的第一种方式:

try{
    //可能出现异常的代码
}catch(异常类型1 变量名1){
    //异常处理
}catch(异常类型2 变量名2){
    //异常处理
}......
finally{
    //一定会执行的代码,即使catch中又出现异常,
    //或try、catch中出现return语句也会执行
    //像数据库连接、输入输出流、网络编程socket等JVM不能自动回收的资源
    //可以在finally中释放
}

通常处理编译时异常
finally不一定要写
没写finally的话,在进入一个catch的异常处理之后跳出try-catch结构
在try结构中声明的变量只能在try结构中调用
常用异常处理方式:
变量名.getMessage() 返回异常信息字符串String
变量名.printStakeTrace() 打印堆栈信息

异常处理的第二种方式:
throw 异常类型

将异常抛给上一级(调用异常处的方法)最迟在main方法处处理
子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型

手动抛出异常

throw new 异常类型   //手动生成异常,如果是编译时异常,要在方法声明处抛出

自定义异常类
1.继承现有的异常结构RuntimeException或Exception
2.提供静态全局常量:serialVersionUID
3.提供重载构造器

一个进程中可能存在多个线程,一个进程在内存中使用一个方法区和堆,每个线程拥有独立的运行栈和程序计数器
一个java程序最少有3个线程:main()主线程,gc()垃圾回收线程,异常处理线程
并行:多个CPU同时执行多个任务。比如:多个人同时做不同的事。
并发:一个CPU(采用时间片)同时执行多个任务。比如:秒杀、多个人做同一件事。

线程创建:
1.继承Thread类,重写run方法,new一个对象,调用start方法(启动线程并运行run方法)
要再启动一个线程需要 重新new一个对象 / 新建一个子类 / 创建Thread类的匿名子类
2.实现Runnable接口。 子类中重写Runnable接口中的run方法。
通过Thread类含参构造器创建线程对象。将Runnable接口的子类对象作为实际参数传递Thread 类的构造器中。
调用Thread类的start方法:开启 线程,调用Runnable子类接口的run方法。

开发中优先选择 实现Runnable接口 的方式

//Thread类的常用方法
currentThread()//静态方法,返回执行当前代码的线程
getName()//获取当前线程的名字
setName()//设置当前线程的名字
yield()//释放当前cpu的执行权
对象.join()//在线程a中调用线程b的join方法,线程a进入阻塞状态,
            //只有线程b执行完之后才结束阻塞状态,需要try catch处理异常
stop()//已过时,强制结束当前线程
sleep()//当前线程睡眠(阻塞)指定ms时间
isAlive()//返回boolean值,判断线程是否存活
线程的优先级等级 MAX_PRIORITY:10 
                MIN _PRIORITY:1 
                NORM_PRIORITY:5
getPriority() //返回线程优先值 
setPriority(int newPriority) //改变线程的优先级

高优先级线程先被执行的概率较大,不是一定先被执行

线程同步
解决线程安全问题·:对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以 参与执行。
1.同步代码块

synchronized(同步监视器 /){//任何类的对象都可以充当锁(类.class也可以,因为类也是对象)
    //需要被同步的代码(操作共享数据)
}

要求:多个线程必须要用同一把锁(同一个对象)

2.同步方法
实现Runnable接口的实现:

private synchronized void method()//锁是this

继承Thread类的子类:

private static synchronized void method()//锁是当前的类

单例模式懒汉式的线程安全
嵌套使用同步锁容易出现线程死锁问题

3.Lock锁

private ReentrantLock lock = new ReentrantLock();
while (true){
    try {
        lock.lock();
        if (tag > 0) {
            System.out.println(Thread.currentThread().getName() + "\t票号:\t" + tag);
            tag--;
        } else
            break;
    }finally {
        lock.unlock();
    }
}

和 synchronized() 的区别:手动锁定、手动解锁

线程通信

wait()//阻塞当前线程,并释放同步监视器
notify()//唤醒被wait的优先级最高的一个线程
notifyAll()//唤醒所有被wait的线程

这三个方法必须在synchronized()代码块或方法中使用,
调用者必须是synchronized()中的同步监视器

sleep()和wait()的异同
相同:都让当前线程进入阻塞
不同:声明位置不同,sleep()在Thread类中声明 wait()在Object类中声明
调用要求不同
是否释放同步监视器

JDK5.0新增线程创建方式
1.实现Callable接口,重写call()方法
与使用Runnable相比, Callable功能更强大些
相比run()方法,可以有返回值
call()方法可以抛出异常
支持泛型的返回值
需要借助FutureTask类,比如获取返回结果

Future接口
可以对具体Runnable、Callable任务的执行结果进行取消、查询是 否完成、获取结果等。
FutrueTask是Futrue接口的唯一的实现类
FutureTask 同时实现了Runnable, Future接口。它既可以作为 Runnable被线程执行,又可以作为Future得到Callable的返回值

2.使用线程池
提前创建好多个线程,放入线程池中,使用时直接获取,使用完 放回池中。可以避免频繁创建销毁、实现重复利用。

//提供指定数量的线程池
ExecutorService service = Executors.newFixedThreadPool(10);
ThreadPoolExecutor service1 = (ThreadPoolExecutor)service;
//设置线程池的属性
service1.setCorePoolSize(15);
//执行指定线程,需要提供实现了Runnable或Callable接口的类的对象
service.execute(new NumberThread());//适合使用runnable
//service.submit();//适合使用callable
service.shutdown();//关闭线程池

ExecutorService:真正的线程池接口。
常见子类ThreadPoolExecutor
void execute(Runnable command) :执行任务/命令,没有返回值,
一般用来执行 Runnable
Future submit(Callable task):执行任务,有返回值,
一般又来执行 Callable
void shutdown() :关闭连接池
Executors:工具类、线程池的工厂类,
用于创建并返回不同类型的线程池
Executors.newCachedThreadPool():创建一个可根据需要创建新线程的线程池
Executors.newFixedThreadPool(n); 创建一个可重用固定线程数的线程池
Executors.newSingleThreadExecutor() :创建一个只有一个线程的线程池
Executors.newScheduledThreadPool(n):创建一个线程池,
它可安排在给定延迟后运 行命令或者定期地执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值