JAVA个人学习笔记

目录

StringBuilder的用法

数组排序后输出原数组下标

字符串排序

对日期处理

staict用法 

extends用法

 int 、 String、 Integer 之间转换

java面试题:为什么String不可变、StringBuffer/StringBuilder可变

统计一个方法的耗费时长(毫秒)

数字格式化

高精度的BigDecimal

生成随机数

二分查找

try{}catch(){}异常处理机制运行步骤

枚举与switch连用

方法重载

构造方法

   封装

static

带static与不带static方法区别

静态代码块

实例代码块

this

extends(继承)

重写(方法覆盖)

多态、instanceof、super

final、finally、finalize区别

抽象类、抽象方法

接口

 java三大特性关系

基本类型和包装类型的区别

集合的概念

集合继承结构图

Collection接口中常用的方法

 Collection接口中contains方法详解

关于集合迭代、遍历 

 面试题:集合当中你用的那个集合最多

 List接口储存元素方法和ArrayList集合使用

 LinkedList集合的使用

 vector集合和(非线程安全)ArrayList集合转换成线程安全

泛型的理解与 使用

自定义泛型

增强for循环

HashSet集合

 TreeSet集合

 Map接口常用的方法和遍历Map集合

  HashMap集合和Hashtable集合

  Properties集合

 TreeSet集合和自定义类型比较排序

 集合工具类Collections

IO流

 InputStream 字节流输入流

OupputStream字节输出流

文件拷贝

FileReader

 FileWriter

 BufferedReader

 InputStreamReader

DataOutputStream和DataInputStream

 PrintStream

 File

目录复制

ObjectInputStream 和ObjectOutputStream

 IO和Properties集合联合

多线程

start()方法解释

线程生命周期获取​编辑取当前线程对象、对象名字、修改线程名字

sleep()方法、interrupt()方法、更好的线程终止方法

常见的线程调度模型

java提供那些方法和线程调度有关

线程安全与synchronize()

java三大变量与线程安全关系

线程守护

定时器

实现线程的第三种方法

反射机制

三种获取字节码文件方式

通过相对路径获取绝对路径两种方法

java.lang.reflect.Field

反射机制访问对象属性

可变长度参数

java.lang.reflect.Method

获取一个类的父类的接口

注解


 

StringBuilder的用法

String number="1234";
        StringBuilder sb=new StringBuilder(number);
        sb.append(56);
        System.out.println(sb);        //123456
        System.out.println(sb.toString());          //1234456     一般与return使用

        sb.insert(6,7);
        System.out.println(sb);   //1234567    位置

        sb.deleteCharAt(6);   //123456   下标
        System.out.println(sb);

        sb.delete(1,2);             //下标,左闭右开
        System.out.println(sb);      //13456

        System.out.println(sb.reverse());        //65431

(1条消息) StringBuilder的用法_爱学习的飞飞的博客-CSDN博客_stringbuilder用法https://blog.csdn.net/qq_50617271/article/details/112686826?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166522486416782391857487%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166522486416782391857487&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-112686826-null-null.142%5Ev52%5Econtrol,201%5Ev3%5Econtrol_1&utm_term=StringBuilder&spm=1018.2226.3001.4187

数组排序后输出原数组下标

import java.util.Arrays;
import java.util.Comparator;
class hh{
    public static void main(String[] args) {
        Integer []arr={1,5,7,4,6,9};
        Integer []arr1=new Integer[arr.length];
        for(int i=0;i<arr.length;i++)
            arr1[i]=i;

        System.out.println("数组元素");
        System.out.println(Arrays.toString(arr));
        
        System.out.println("排序前数组元素下标");
        Arrays.sort(arr1, Comparator.comparingInt(i->arr[i]));
        System.out.println(Arrays.toString(arr1));

        System.out.println("排序后数组元素");
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));

    }
}

字符串排序

class hh{
    public static void main(String[] args) {
        String arr="cba";
        char []arr1=arr.toCharArray();
        Arrays.sort(arr1);
        System.out.println(arr1);
    }
}

对日期处理

        Date date=new Date();
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:sss");
        System.out.println(sdf.format(date));

(7条消息) Java中for(:)的使用_我会好好吃饭歌的博客-CSDN博客_for(:) javahttps://blog.csdn.net/qq_45363655/article/details/106108646?ops_request_misc=&request_id=&biz_id=102&utm_term=java%E4%B8%ADfor%E9%87%8C%E9%9D%A2%E7%9A%84%EF%BC%9A&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-106108646.142%5Ev53%5Econtrol,201%5Ev3%5Econtrol_1&spm=1018.2226.3001.4187

staict用法 

(7条消息) java中static归纳总结_指尖绽放奇迹的博客-CSDN博客https://blog.csdn.net/qq_41457412/article/details/80598787?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166564406116800186546483%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166564406116800186546483&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-80598787-null-null.142%5Ev55%5Epc_search_v3,201%5Ev3%5Econtrol_1&utm_term=java%E4%B8%ADstaic&spm=1018.2226.3001.4187

extends用法

(7条消息) Java 继承详解(extends)_............1的博客-CSDN博客_extends javahttps://blog.csdn.net/qq_43751200/article/details/123445623?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166564518816800182166582%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166564518816800182166582&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-123445623-null-null.142%5Ev55%5Epc_search_v3,201%5Ev3%5Econtrol_1&utm_term=extends&spm=1018.2226.3001.4187

 int 、 String、 Integer 之间转换

//int ->String
        int i=1;
        String j=String.valueOf(i);
        //或者
        String k=i+"";


        //String -> int
        String n="123";
        int m=Integer.parseInt(n);


        //int ->Integer
        int q=1;
        Integer in=q;
        //或者直接转,系统自动装箱
        Integer ine=1;


        //Integer -> int
        Integer w=1;
        int e=w;
        //或者直接转,系统自动拆箱
        int r=1;


        //String -> Integer
        String a="ad";
        Integer s=Integer.valueOf(a);
        
        //Integer ->String 
        Integer x=1;
        String c=String.valueOf(x);

java面试题:为什么String不可变、StringBuffer/StringBuilder可变

        我看过源代码,String类中有一个bety[ ]数组,这个bety[ ]数组采用了final修饰,因为数组一旦创建长度不可变。并且被final修饰的的引用对象一但指向某个对象之后,不可再指向其他对象,所以String是不可变的!

我看过源代码,StringBuffer/StringBuilder内部实际上是一个bety[ ]数组,这个bety[ ]数组没有被final修饰,StringBuffer/StringBuilder的初始化容量我记得大致是16,当存满之后会进行扩容,底层采用了数组拷贝的方法System.arraycopy()...是这样扩容的。所以StringBuffer/StringBuilder适合字符串频繁拼接

统计一个方法的耗费时长(毫秒)

        long begin=System.currentTimeMillis();
        for(int i=0;i<1000;i++){
           System.out.println(i);
        }
        long end=System.currentTimeMillis();
        System.out.println(end-begin);

数字格式化

        //#代表任意数字
        //,代表千分位
        //.代表小数点后几位
        //0代表不够不零

        DecimalFormat df=new DecimalFormat("###,###.0000");
        System.out.println(df.format(1234.567));

高精度的BigDecimal

        //1.BigDecimal属于大数据,精度极高,不属于基本数据类型,属于java对象(引用数据类型)是                
        //SUN公司提供的一个类。专门在财务软件中
        //2.注意财务中double是不够的,当面试的时候经理问你处理财务数据吗,用的是那种类型
        //不要说是double,说java.math.BigDecimal

        BigDecimal v1=new BigDecimal(100);
        BigDecimal v2=new BigDecimal(200);
        BigDecimal v3=v1.add(v2);      //不能用+-*/应该用math里面的方法
        System.out.println(v3);

生成随机数

        Random rd=new Random();
        //产生一个int类型的随机数
        int num=rd.nextInt();
        System.out.println(num);
        //产生一个有范围的随机数,nextInt翻译为:下一个int类型的数据,表示只能取到100
        int num2= rd.nextInt(1001);
        System.out.println(num2);

二分查找

        int []arr={1,5,2,3,9};
        Arrays.sort(arr);
        int num1=Arrays.binarySearch(arr,5); //找到返回大于0
        int num2=Arrays.binarySearch(arr,7);  //没找到返回小于0
        System.out.println(num1);
        System.out.println(num2);

try{}catch(){}异常处理机制运行步骤

 //防止当出现异常代码不能运行
        try{
            int i=10/0;   //当出现异常直接进入catch语句
            System.out.println(i);
        }catch (Exception e){
            System.out.println("输入不合法");
        }

枚举与switch连用

public class main {
    public static void main(String[] args) {
        switch (Season.SPRING){
            case SPRING -> System.out.println("春天");
            case SUMMER -> System.out.println("夏天");
            case AUTUMN -> System.out.println("秋天");
            case WINTER -> System.out.println("冬天");
        }
    }
}
enum Season{
    SPRING,SUMMER,AUTUMN,WINTER
}

方法重载

public class Test {
    public static void main(String[] args) {
        //方法重载
        //缺点:功能“相似”,作用“相似”,代码不美观
        System.out.println(add(1,2));
        System.out.println(add(1.0,2.1));
        System.out.println(add(1.1,2.2));

    }
    public static  int add(int i,int j){
        return i+j;
    }
    public static double add(double i,double j){
        return i+j;
    }
    public static float add(float i,float j){
        return i+j;
    }
}

构造方法

public class ConstructorMethod {
    //一个类如果没有构造方法,那么会有一个默认的无参构造方法
    //构造方法的作用是个实例变量(全局变量)初始化
    int i;
    ConstructorMethod(){

    }
    ConstructorMethod(int i){
        this.i=i;
    }
}

   封装

public class Encapsulation {
    //封装的两个作用
    //保证内部结构安全
    //屏蔽复杂,暴露简单
    //一个类体当中的数据,在封装之后,对于代码调用人员来说
    //不需要关心代码的复杂实现,只需要通过一个简单的入口就可以访问
    //另外类体安全的级别高的数据封装起来,外部人员不能随意访问
    //来保证数据的安全
    public static void main(String[] args) {
        Data d=new Data();
        System.out.println(d.getData());
        d.setData(3);
    }
}
class Data{
    int data;

    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }
}

static

//static翻译为“静态”
//所有static修饰的关键字都是类相关的,类级别的
//所有static修饰的,采用“类名.”访问
//static修饰的变量:静态变量  ,静态变量储存在方法区中
//static修饰的方法:静态方法 ,里面不能用静态变量
//非static修饰的方法:实例方法 ,里面不能用静态变量

//方法体外变量:成员变量
//方法体中变量:局部变量 ,里面不能用静态变量  ,储存栈中

//成员变量可以分:
//实例变量:储存在堆中
//静态变量:储存方法区


//静态代码块
//一个类可以多个静态代码块
//静态代码块在类加载时候执行
//静态代码块自上而下执行
//静态代码块只执行一次

带static与不带static方法区别

public class Mothod {
    public static void main(String[] args) {
        M.doSome(); //带static方法,通过类名.调用。
                    //若通过对象.调用在运行阶段JVM会自动转换成类名.调用


        M m=new M();//不带static方法,通过对象.调用
        m.doOther();
    }
}
class M{
    public static void doSome(){
        System.out.println("带static的方法");
    }
    public void doOther(){
        System.out.println("不带static的方法");
    }
}

静态代码块

   //静态代码块
    //一个类可以多个静态代码块
    //静态代码块在类加载时候执行
    //静态代码块自上而下执行
    //静态代码块只执行一次
    static {
        System.out.println("A");
    }

    static {
        System.out.println("B");
    }

    public static void main(String[] args) {
        System.out.println("主函数执行了");     //ABC主函数执行了
    }

    static {
        System.out.println("C");
    }
}

实例代码块

public class Test {
    //实例代码块
    //在new对象之前执行
    //每new一次对象执行一次
    public static void main(String[] args) {
        System.out.println("main 函数执行");
        new S();
        new S(1);
                   //结果:main 函数执行
        //实例代码块执行
        //无参构造函数执行
        //实例代码块执行
        //有参构造函数执行
    }
}
class S{
    {
        System.out.println("实例代码块执行");
    }
    int i;
    S(){
        System.out.println("无参构造函数执行");
    }
    S(int i){
        System.out.println("有参构造函数执行");
    }
}

this

//this表示当前对象 ,一个对象一份,存在对象里面
//this是关键字
//this是变量
//this 是个引用,保存当前对象内存地址
//this 存在堆内存
//this 只使用实例方法中和构造方法

extends(继承)

public class Static {
    //继承 extends
    //子类继承父类,除构造方法和private修饰的数据外,其他都可以继承
    //若类没被继承,默认Object
    //继承的缺点:耦合度高,父类修改,子类受到牵连
    public static void main(String[] args) {
        Cat cat=new Cat();
        cat.doSome();   //动物
    }
}
class Animal{
    public void doSome(){
        System.out.println("动物");
    }
}

class Cat extends Animal{
    
}

重写(方法覆盖)

public class Static {
    //重写(方法覆盖)
    //父类无法满足子类需求
    //重写的条件
    //继承关系
    //相同方法名、返回类型、参数列表
    //访问权限不能低,只能更高
    //子类的重写的方法抛出异常不能多于父类
    
    //方法重写注意事项
    //方法覆盖只针对方法,和属性无关
    //私有方法无法覆盖
    //方法覆盖只针对‘实例方法’,静态方法没有意义    


    //重写与重载有区别
    //重载是单独类中
    //重写是在继承中
    
    public static void main(String[] args) {
        Cat cat=new Cat();
        cat.doSome();     //猫
    }
}
class Animal{
    public void doSome(){
        System.out.println("动物");
    }
}

class Cat extends Animal{
        public void doSome(){
            System.out.println("猫");
        }
}

多态、instanceof、super

public class Static {
    //多态
    //也称上转型
    //多态指的是父类型引用指向子类型对象
    //编译阶段绑定父类行方法、
    //运行阶段动态绑定子类型对象方法

    public static void main(String[] args) {
        Animal cat=new Cat();
        cat.doSome();     //猫
        //分析cat.doSome()
        //java程序分为编译阶段和运行阶段
        //先编译阶段:
        //对于编译器来说,编译器只知道cat是Animal类型
        //所以编译器在检查语法的时候,会去Animal.class字节码中找到doSome()方法
        //找到了,绑定doSome()方法,静态绑定成功(编译阶段属于静态绑定)
        //然后进入运行阶段:
        //在运行阶段的时候,实际上java在堆内存中创建的是Cat的对象
        //所以doSome的时候,真正参与doSome的对象是猫,
        //运行阶段则会执行Cat对象的doSome的方法(运行阶段属于动态绑定)


        ((Cat)cat).mySome();  //结果是:鸟子类特有的方法    调用子类特有的方法需要强制类型转换、也称下转型



        //instanceof运算符
        //在强制类型转换时候,为了避免转换类型与对象类型不一致
        //运算的结果为true/false
        if (cat instanceof Cat){
            ((Cat)cat).mySome();  //虽然看的很鸡肋,但子类多了就不一样
        }



        //super:
        //要想多态必须继承,那么问题来了
        //继承的时候构造方法无法继承
        //这个时候super来了
        //super能出现在实例方法和构造方法中
        //语法是super.和super()
        //super不能使用在静态方法中
        //super()只能出现在构造方法第一行,通过当前的构造方法调用父类中构造方法(目的是代码复用)
        //当子类构造方法没有使用super(),系统自动加super()调用父类无参构造方法
        //super.可以访问父类方法也可以访问父
        //super 不是引用,也不保存地址,也不指向对象类属性
        //super 只是代表当前对象内部的那一块父类型特征
    }
}
class Animal{

    int i;
    Animal(){

    }
    Animal(int i){
        this.i=i;
    }
    public void doSome(){
        System.out.println("动物");
    }
}

class Cat extends Animal{

        int i;
        int j;
        Cat(){

        }
        Cat(int i,int j){
            super(i);
            this.j=j;
        }
        public void doSome(){
            System.out.println(i);        //子类的值
            System.out.println(this.i);   //子类的值
            System.out.println(super.i);  //父类的值
            System.out.println("猫");
            super.doSome();
        }

        public void mySome(){
            System.out.println("猫子类特有的方法");
        }
}

final、finally、finalize区别

     //final
    //final修饰的类无法继承
    //final修饰的方法无法覆盖
    //final修饰的变量不能重新赋值

   //finally
  //和try一起联合sy
  //finally语句块里面是一定执行的

  //finalize
//是Object类中的方法名
//这个防范由垃圾回收器调用

抽象类、抽象方法

public class Abstract {
    /*
    * 抽象类
    * 类与类具有共同特征,将这些共同特征提取出来,形成的就是抽象类
    * 抽象类是引用数据类型
    * 抽象类本身是不存在的,无法创建对象,(无法实例化)
    * 抽象类可以被继承,子类是可以实例化,子类一定要实现抽象方法,(继承了,
    * 相当于把父类方法复制一份到子类中
    * 但是由于抽象方法必须要出现在抽象类中)
    * 抽象类可以有构造方法
    * 抽象类一般与继承关联,
    * 抽象类中不一定要有抽象方法
    * 抽象类中可以有非抽象方法
    * 抽象方法一定要在抽象类中
    * */
    public static void main(String[] args) {
        A c=new B();  //这就是面向抽象编程
        c.a();
    }
}
abstract class A{
    int i;
    A(){

    }
    A (int i){
        this.i=i;
    }
    public abstract void a(); //抽象方法
    
    public void b(){        
        System.out.println("hh");
    }
}
class B extends A{
    @Override
    public void a() {       //实现抽象方法,也可以将B类继续抽象就可以不用实现
        System.out.println("w");
    }
}

接口

public class Interface {
    /*
    * 接口也是一种数据类型
    * 接口是完全抽象的,(抽象类是半抽象的)
    * 接口支持多继承
    * 接口只包括两个内容,常量和抽象方法(接口中只要定义变量就自动转换常量)
    * */
    public static void main(String[] args) {
        
    }
}

interface A{    //定义接口            
    
}
interface B extends A{
    
}
interface C extends A,B{ 
    public static final double PI=3.14;
    int i=19;
    
    //public abstract int a();
    int a();  //两个都可以
}

class hh implements C ,A{
    public int a(){       //这里的public不能省,因为默认的比这个低
        System.out.println("ddd");   //实现接口
        return 0;
    }
}

 java三大特性关系

基本类型和包装类型的区别

1.包装类型可以为null,基本类型不行(数据库中若用基本类型会空指针异常)

2.包装类型可以用泛型

3.两个包装类型值可以相等,当不相等(当在100以内是相等的,java有什么机制)

4.自动拆箱装箱

集合的概念

什么是集合、集合有什么用?
数组就是集合,集合是个容器,可以容纳其他类型数据

集合为什么说在开发中使用较多?
集合是一个容器,是一个载体,可以一次容纳多个对象,
在实际开发中,假设连接数据库,数据库当中有10条记录,
那么假设把这都查询出来,在java中会有10条数据封装成10个对象
然后把封装成的10个java对象放到某一个集合当中,将集合传到前端,然后
遍历集合,将数据一个一个展现出来

集合不能直接储存基本数据类型,集合不能直接储存java对象
集合储存的都是java对象内存地址或者说是引用

在java中每个不同的集合,对应不同的数据结构,往不同的集合中储存元素,等于将数据放的不同的数据结构中
 
集合在java.util.*包下

集合继承结构图

Collection接口中常用的方法

    /*
    * Collection接口中常用的方法
    *
    * Collection中能放什么元素?
    * 没有使用“泛型”可以使用Object子类中所有的方法
    *
    * Collection中常用的方法
    *
    * boolean add(Object)  //向集合中添加个数
    * int size()      //获取集合中个数
    * void clear()     //清空集合
    * boolean contains(Object o)      //判断集合中是否有元素o  ,包含返回ture 不false
    * boolean remove(Object o)        //删除o元素
    * boolean isEmpty                 //判断集合是否为空
    *Object[] toArray()               //将集合转换数组
    *
     * */
    public static void main(String[] args) {
    Collection c=new ArrayList();

    c.add(1200);//自动装箱,实际上是放进去一个对象内存地址。Integer x=new Integer();
    c.add(new Object());
    c.add(true);
    c.add(new Student());

    //获取集合中元素个数
        System.out.println("集合中元素个数"+c.size());

        //清空集合
        c.clear();
        System.out.println("集合中元素个数"+c.size());

        //添加元素
        c.add("qq");
        c.add("aer");
        c.add("周添加");

        //判断集合是否包含某个元素
        boolean f=c.contains("周添加");
        System.out.println(f);


        //删除o元素
        c.remove("周添加");

        //判断集合是否为空
        System.out.println(c.isEmpty());

        //将集合转换数组
        Object[] objects=c.toArray();
        for (int i=0;i<objects.length;i++){
            System.out.println(objects[i]);
        }


    }

}
class Student{

}

 Collection接口中contains方法详解

public class CollectionTest3 {
    public static void main(String[] args) {
        Collection c = new ArrayList();
        User user1 = new User("jake");
        User user2 = new User("jake");

        c.add(user1);
        System.out.println(c.contains(user1));

        System.out.println(c.contains(user2)); //底层调用equals方法比较
        System.out.println(user1.equals(user2));
    }
}
class User{
    private String name;

    public User() {
    }

    public User(String name) {
        this.name = name;
    }

//    @Override
//    public boolean equals(Object o) {
//        if (o==null||!(o instanceof User)) return false;
//        if(o==this) return true;
//        User u=(User) o;
//        return u.name==this.name;
//    }
}

关于集合迭代、遍历 

public class CollectionTest2 {
    /*
    * 关于集合迭代、遍历
    * 下面的遍历、迭代是所有Collection通用的方式
    * 在Map集合不能使用
    * 在所有Collection子类使用
    * */
    public static void main(String[] args) {
        Collection c=new ArrayList();   //后面无所谓,重要看Collection接口怎么迭代、遍历
        c.add("asd0");
        c.add(100);
        c.add(new Object());

        //对集合迭代、遍历
        //第一步,获取集合中迭代器对象Iterator
        Iterator i=c.iterator();

        //第二步,通过以上迭代器对象进行迭代、遍历

              //下面两个方法是迭代器Iterator中的方法
              //boolean hasNext()如果“仍”有元素可以迭代,返回ture,(开始指向-1,集合下标从0开始)
              //Object next()返回迭代的下一个元素
//        for (int j=0;j<c.size();j++){
//            if (i.hasNext()){
//                System.out.println(i.next());
//            }
//        }
        //可以这样写
        while (i.hasNext()){
            Object o= i.next(); //迭代器返回的是Object类型,不能用其他类型接收
            //c.remove(100);
            //上面一行代码会出现问题
//            Exception in thread "main" java.util.ConcurrentModificationException
//            at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1013)
//            at java.base/java.util.ArrayList$Itr.next(ArrayList.java:967)
//            at Test.CollectionTest2.main(CollectionTest2.java:38)
            //迭代器获取了元素转换,若改边了集合中的结构则会出现异常

            //使用迭代器中的remove方法可以同时删除迭代器和集合的元素,这个是删除大当前指向的元素
            i.remove();
            System.out.println(o);
            //System.out.println(i.next());
        }


    }

}



 面试题:集合当中你用的那个集合最多

答:ArrayList集合,向数组末尾添加元素效率不受影响

       另外数组检索、查找比较多,效率高(每个元素占用可以大小一样,内存地址连续,通过数学表达式算出内存地址)

 List接口储存元素方法和ArrayList集合使用

public class ListText
{
    /*
    * List接口储存元素方法的特点:
    * 有序(有下标),可重复
    *
    * List接口既然是Collection接口的子接口,那么肯定有自己特有的方法
    *void add(int index,Object o)   用下标添加元素
    * int indexOf(Object o)         判断元素第一次出现的下标,存在返回下标,不存在返回-1
    *    * Object get(int index)         根据下标获取元素
    * int lastIndexOf(Object o)      判断元素最后一次出现的下标,存在返回下标,不存在返回-1
    * Object remove(int index)       删除
    * Object set(int index,Object element)    改
    *
    *
    * ArrayList集合初始化容量是10(底层先创建长度是0的数组,当添加第一个元素的时候,初始化容量是10)
    * ArrayList底层是调用Object[]数组
    *ArrayList扩容是1.5倍
    *ArrayList是非线程安全的
     * */
    public static void main(String[] args) {
        List i =new ArrayList();
        List k=new ArrayList(20);
        i.add("sd");
        i.add("we");
        i.add("df");

        Collection v=new HashSet();
        v.add(1);
        v.add(2);
        v.add(3);
        List l=new ArrayList(v);   //通过这个构造方法可以将HashSet集合转换成ArrayList集合

        
        //添加元素,并不会将下标二的元素覆盖只是将下标2的元素后移
        i.add(2,"ll");


        Iterator c=i.iterator();
        while (c.hasNext()){
            System.out.println(c.next());
        }


        System.out.println("------------");


        System.out.println(i.get(0));
        //可以通过这个遍历集合
        for (int j=0;j<i.size();j++){
            System.out.println(i.get(j));
        }

        System.out.println(i.indexOf("sd1"));
    }
}

 LinkedList集合的使用

public class LinkedListTest {
    /*
    * 链表优点
    * 元素地址不连续,随机删除某个元素不会出现大量元素位移
    *
    * 缺点
    * 不能通过数学表达式计算元素地址,每次查找都需要遍历
    *     * */
    public static void main(String[] args) {
        List l=new LinkedList();
        l.add(1);
        l.add(2);
        l.add(3);


        //注意LinkList也有下标,
        //ArrayList检索效率高不单单是下标,底层是数组,内存地址连续,可以通过数学表达式计算元素地址
        for (int i=0;i<l.size();i++){
            System.out.println(l.get(i));
        }
    }
}

 vector集合和(非线程安全)ArrayList集合转换成线程安全

/*vector集合
    * 底层也是一个数组
    * 初始容量是10
    * 扩容是2倍
    *Vector中所有的方法都是线程同步的,都带有synchronized关键字,是线程安全的
    * 效率较低,使用较少
    *
    *
    * 怎么将将ArrayList集合转换成线程安全
    * 使用集合工具类:
    *  java.util.Collections;
    *   java.util.Collections; //是集合工具类
    *  java.util.Collection;  // 集合接口
    *
    * 
     * */
    public static void main(String[] args) {
        List v=new Vector();

        v.add(1);
        v.add(1);
        v.add(1);
        v.add(1);
        v.add(1);

        Iterator i=v.iterator();
        while(i.hasNext()){
            System.out.println(i.next());
        }
        
        List z=new LinkedList();   //非线程安全
        z.add(1);
        z.add(1);

        Collections.synchronizedList(z);  //线程安全了
        
    }
}

泛型的理解与 使用

/*
* 泛型
* jdk5之后退出特性
* 只在编译阶段起作用,只是给编译器参考的(运行阶段不起作用)
* 
* 好处
* 类型统一
* 不需要大量强制类型转换(父类不用转型,子类还是需要转型的)
* 
* 缺点
* 元素多样形少
* 
* 
* jdk8之后引入:自动类型表达式(又称钻石表达式)
* 
* */
public class GenericTest {
    public static void main(String[] args) {
        //没有使用泛型
        All a=new Bll();
        All b=new Cll();
        List list=new LinkedList();
        list.add(a);
        list.add(b);
        Iterator iterator=list.iterator();
        while (iterator.hasNext()){
            Object o=iterator.next();
            if (o instanceof Bll){
                ((Bll) o).m();

            }
            if (o instanceof Cll){
                ((Cll) o).k();
            }

        }

        //使用泛型
        //指定这个集合只能储存All,当然我Bll和Cll继承了也可以使用
    
        All a1=new Bll();
        All b1=new Cll();
        List<All> list1=new LinkedList<All>();
       // List<All> list1=new LinkedList<>();   //LinkedList<All>中的All可以不写,jdk可以自动推断

        list1.add(a1);
        list1.add(b1);
        //list1.add(1);  //这个就不行了
        Iterator<All> iterator1=list1.listIterator();
        while (iterator1.hasNext()){
            Object o1=iterator1.next();
            if (o1 instanceof Bll){
                ((Bll) o1).m();
                ((Bll) o1).move1();
            }
            if (o1 instanceof Cll){
                ((Cll) o1).k();

            }
        }

    }
}
class All{
    public void move1(){
        System.out.println("hh");
    }
}
class Bll extends All{
    public void m(){
        System.out.println("jj");
    }
}
class Cll extends All{
    public void k(){
        System.out.println("rr");
    }
}

自定义泛型

/*自定义泛型
*  <> 里面可以随便写,标识符
* java源代码中的<E>、<T>
E是Element
* T是Type
* */
public class GenericTest { 
    public static void main(String[] args) {
       A<String> i=new A<>(); //<> 里面可以随便写,标识符
       i.get();
       //int j=i.get();  //类型不匹配,指定的是String类型
        
    }
}
class A<T>{
    public T get(){
        return null;
    }
}

增强for循环

public class ForEachTest {
    public static void main(String[] args) {
        int []a={1,2,34,5,6};
        for (int i=0;i<a.length;i++){
            System.out.println(a[i]);
        }

        //增强for循环
        //for(元素类型 变量名:数组或集合){}
        for (int data:a
             ) {
            //data代表数组中的元素(foreach循环的缺点:没有下标)
            System.out.println(data);
        }
        List<String> list=new LinkedList<>();
        list.add("dsa");
        list.add("ewr");
        for (String s:list
             ) {
            System.out.println(s);   //可以不用使用迭代器

        }
    }
}

HashSet集合

/*
* HashSet集合
*无序不重复
* 储存的循序与取出的循序不同
* 放到HashSet集合的元素实际上放到了HashMap集合的Key部分去了
* */
    public static void main(String[] args) {
        Set<String> s=new HashSet<>();
        s.add("ds");
        s.add("eqw");
        s.add("gf");
        s.add("gf");

        for (String s1:s
             ) {
            System.out.println(s1);
        }
        
    }
}

 TreeSet集合

/*
    * TreeSet集合
    *
    * 无序不可重复
    * 但是储存的元素自动排序
    *
    * */
    public static void main(String[] args) {
        Set<Integer> i=new TreeSet<>();
        i.add(2);
        i.add(4);
        i.add(1);
        i.add(3);
        for (Integer i1:i
             ) {
            System.out.println(i1);    //1,2,3,4

        }
    }
}

 Map接口常用的方法和遍历Map集合

public class MapTest {
    /*
    * Map接口常用的方法
    * Map和Collection没有继承关系
    * Map集合以key和value方式储存:键值对
    * key 和value都是引用数据类型
    * key和value都是对象内存地址
    * key 起主导作用,value是key的附属品
    *
    * Map接口常用的方法:
    * V put(K key, V Value)向Map集合添加键值对
    * V get(Object key)通过key获取value
    * void clear()清空Map集合
    * boolean containsKey(Object key)判断Map中是否包含value
    * boolean isEmpty() 判断Map集合是否为0;
    * Set<K> keySet()获取Map集合所有key(所有的键是一个Set集合)
    * V remove(Object key)通过key删除键值对
    * int size()获取Map集合键值对的个数
    * Collection<V> values() 获取Map集合所有的value 返回一个Collection集合
    * Set<Map.Entry<K,V>> entrySet() 将Map集合转换Set集合
    * 解释:
    * map1集合对象
    * key                  value
    * 1                    zhangsan
    * 2                    lisi
    * 3                    wangwu
    * Set set =map1.entrySet();
    * set集合对象
    * 1=zhangsan  (注意Map集合通过entrySet()方法转换成Set集合,set集合中元素类型是Map.Entry<K,V>)
    * 2=lisi       (Map.Entry 和String一样,都是一种类型的名字,只不过Map.Entry是静态内部类,是Map中的静态类)
    * 3=wangwu   --->这个东西是Map.Entry
    *
    *遍历Map集合
    *
    *
    * */
    public static void main(String[] args) {
        Map<Integer, String> map=new HashMap<>();
        //添加
        map.put(1,"zhangsan");
        map.put(2,"lisi");
        map.put(3,"wangwu");

        //通过key获取value
        System.out.println(map.get(2));

        //获取jzd
        System.out.println("键值对"+map.size());

        //删除key删除键值对
        map.remove(1);

        //判断是否包含某个key
        System.out.println(map.containsKey(2));

        //判断是否包含某个value
        System.out.println(map.containsValue("zhangsan"));

        //获取所有的value
        //第一种方法,获取所有的key 遍历key,从而遍历value
        Collection<String> c=map.values();
        for (String s:c
             ) {
            System.out.println(s);
        }

        Set<Integer> keys=map.keySet();
        //使用迭代器
        Iterator<Integer> k=keys.iterator();
        while (k.hasNext()){
            Integer ke=k.next();
            String value =map.get(ke);
            System.out.println(ke+"="+value);
            //System.out.println(k.next()+"="+map.get(k.next()));
        }
        //使用foreach
        for (Integer ke:keys
             ) {
            System.out.println(ke+"="+map.get(ke));

        }

        //第二种方式:Set<Map.Entry<K,V>> entrySet()
        //将Map集合转换成Set集合
        //Set集合类型是Map.Entry
        Set<Map.Entry<Integer,String>> set=map.entrySet();
        //遍历Set集合每次取出一个Node

        //迭代器
        Iterator<Map.Entry<Integer,String>> it= set.iterator();
        while (it.hasNext()){
            Map.Entry<Integer,String> node=it.next();
            Integer key =node.getKey();
            String value = node.getValue();
            System.out.println(key+"="+value);
        }
        //foreach
        //这种方式效率高
        for (Map.Entry<Integer,String> node:set
             ) {
            System.out.println(node.getKey()+"="+ node.getValue());

        }
    }
}

  HashMap集合和Hashtable集合

public class HashMapTest{
    /*
    * HashMap集合和Hashtable集合
    * HashMap集合允许key和value值为null,只允许一个
    * Hashtable集合不允许key和value值为null
    *
    * HashMap集合和Hashtable集合底层是哈希表/散列表数据结构
    * 哈希表是数组和单链表的结合体
    * 数组在查询效率高
    * 单链表在随机增删效率高
    *
    *
    * 放在HashMap集合的key部分的key元素和HashSet集合中的元素需要重写equals()和hashCode()方法
    * HashMap集合和Hashtable集合, HashMap集合默认初始化容量是16,,Hashtable集合默认初始化容量是11,默认加载因子是0.75(底层数组容量达到75%,数组开始扩容)
    *HashMap初始化容量要是2的倍数,可以达到散列均匀,通过存取效率
    * Hashtable集合扩容是*2+1
    * */

    public static void main(String[] args) {
        Map map=new HashMap();

    }
}

  Properties集合

public class PropertiesTest {
    /*
    * Properties是一个Map集合,继承了Hashtable,Properties的key和value值都为String类型
    * Properties称为属性类对象
    * Properties是线程安全的
    * */
    public static void main(String[] args) {
        Properties p=new Properties();
        p.setProperty("fds","gsdf");
        System.out.println(p.getProperty("fds"));

    }
}

 TreeSet集合和自定义类型比较排序

public class TreeSetText {
    /*
    * TreeSet集合底层实际上是TreeMap
    * TreeMap集合底层实际上是二叉树
    * 放到TreeSet集合中的元素实际上放到了TreeMap集合key部分
    * TreeSet集合无序不可重复,但是可以按元素大小排序
    * 对自定义类型排序需要重写接口Comparable中的compareTo()ff
    * */
    public static void main(String[] args) {
    Name a1=new Name(1,"dsa");
    Name a2=new Name(2,"dad");
    Name a3=new Name(3,"re");
    Name a4=new Name(4,"fg");
    //重写compareTo比较
        Set<Name> list=  new TreeSet();
        list.add(a1);
        list.add(a2);
        list.add(a3);
        list.add(a4);
        for (Name i:list
             ) {
            System.out.println(i);
        }

    //通过比较器接口比较
        User u1=new User(2);
        User u2=new User(1);
        User u3=new User(3);
        Set<User> set=new TreeSet<>(new Usercompar());//比较器接口对象,若比较经常切换建议使用这个,可以写别的比较数据
        set.add(u1);
        set.add(u2);
        set.add(u3);
        for (User u:set
             ) {
            System.out.println(u);

        }
    }
}
class Name implements Comparable<Name> {
  int age;
  String name;

    public Name(int age, String name) {
        this.age = age;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Name{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }

    @Override
    public int compareTo(Name o) {
        if (this.age==o.age)
            this.name.compareTo(o.name);  //String已经重写了compareTo方法
        return this.age-o.age;
    }
}

class User {
    int age;

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                '}';
    }

    public User(int age) {
        this.age = age;
    }


}
class Usercompar implements Comparator{

    @Override
    public int compare(Object o1, Object o2) {
        return ((User)o1).age-((User)o2).age;
    }
}

 集合工具类Collections

public class collectionsTest {
    public static void main(String[] args) {
        List<Integer> list=new ArrayList();  //线程不安全
        Collections.synchronizedList(list);//线程安全了
        list.add(2);
        list.add(1);
        list.add(3);
        Collections.sort(list);    //调用集合工具类排序
        for (Integer i:list
             ) {
            System.out.println(i);
        }
        Set<User1> s=new TreeSet<>();
        s.add(new User1(2));
        s.add(new User1(3));
        s.add(new User1(1));
        //Collections.sort(s);  //只支持List接口
        List<User1> list1=new ArrayList<>(s);
        Collections.synchronizedList(list1);
        Collections.sort(list1);
        for (User1 u:list1
             ) {
            System.out.println(u);
        }
    }
}
class User1 implements Comparable{
    int age;

    @Override
    public String toString() {
        return "User1{" +
                "age=" + age +
                '}';
    }

    public User1(int age) {
        this.age = age;
    }

    @Override
    public int compareTo(Object o) {
        return this.age-((User1)o).age;
    }
}

IO流

(1)字节流一次读8位二进制

字符流一次读一个字符

(2)IO流四大家族(都是抽象类):

java.io.InputStream 字节流输入流

java.io.OutputStream字节输出流

java.io.Reader字符输入流

java.io.Writer字符输出流

在java中类名以Stream结尾是字节流,以Reader/Weiter结尾是字符流

(3)所有流都实现了 java.io.Closeable 接口,都是可关闭的,都有close()方法

(4)所有的输出流实现了 java.io.Flushable 接口,都是可刷新的(让通道中残余的数据强行输出   完),都有flush()方法 

(5)java.io中需要掌握16个流

      文件专属流:

                java.io.FileInputStream 

                java.io.FileOutputStream

                java.io.FileReader

                java.io.FileWriter

      转换流(字节流转换字符流)

                java.io.BufferedInputStream 

                java.io.BufferedOutputStream

                java.io.BufferedReader

                java.io.BufferedWriter

     数据专属流

                java.io.DataInputStream 

                java.io.DataOutputStream

标输出流

                java.io.PrintReader

                java.io.PrintWriter

对象专属流

                java.io.ObjectInputStream 

                java.io.ObjectOutputStream

 InputStream 字节流输入流

public class FileInputStreamTest {
    /*
    * 文件字节输入流,任何类型的文件都可以采用这个流来读
    *
    * */
    public static void main(String[] args) {
        FileInputStream fileInputStream=null;
        try {
            fileInputStream =new FileInputStream("E:\\桌面\\桌面\\d1");

            //开始读
            //int dataRead =fileInputStream.read();//这个方法返回的是这个“字节”的本身asccll
          //  System.out.println(dataRead);//读到文件末尾返回-1, 一次只能读一个字节
/*
            while (true){
                int l=fileInputStream.read();
                if (l==-1 ) {
                    break;
                }
                System.out.println(l);
            }
*/
 /*           //改造while
            int k=0;
            while ( (k=fileInputStream.read())!=-1){
                System.out.println(k);
            }

  */
            /*
            //以上都是一次读一个字节
            //向byte[]数组里面读
            byte[]bytes=new byte[4];
            //int f=fileInputStream.read(bytes);
            //System.out.println(f);//4,返回的是数量不是内容
            //将字节转换字符串
            //System.out.println(new String(bytes));  //asdf
            System.out.println(new String(bytes,0,fileInputStream.read(bytes)));//加范围

            //System.out.println(new String(bytes));  //gsdf,只有五位数字最后一位只覆盖了a,其他没有覆盖照常输出
            System.out.println(new String(bytes,0,fileInputStream.read(bytes)));



             */

            //改进
/*
            byte[] bytes=new byte[4];
            int newBytes;
            while ((newBytes=fileInputStream.read(bytes))!=-1){
                System.out.println(new String(bytes,0,newBytes));
            }

*/

            //int available()返回流中还没有读到字节数量
            byte[] bytes=new byte[fileInputStream.available()];//不适合太大文件
            System.out.println(fileInputStream.available());
            int c=fileInputStream.read(bytes);
            System.out.println(new String(bytes));

            //loog skip()跳过几个字节不读
            fileInputStream.skip(3);
            System.out.println(fileInputStream.read());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (fileInputStream != null) {//关闭流的前提是流不为null,为null关闭没有意义
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

OupputStream字节输出流

public class FileOutputStreamTest {
    public static void main(String[] args) {
        FileOutputStream fileOutputStream=null;
        try {
            fileOutputStream=new FileOutputStream("dd",true);  //没有dd文件会自动创文件,若有会先清空文件内容再写入
            byte[] bytes={98,45,65,100};                                       //后面加true就不会清空
            fileOutputStream.write(bytes);//b-Ad
            fileOutputStream.write(bytes,0,2);//b-Adb-   写一部分

            String s="周添加牛逼,6666";
            fileOutputStream.write(s.getBytes());
            fileOutputStream.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

文件拷贝

public class Copy {
    public static void main(String[] args) {
        FileInputStream fileInputStream=null;
        FileOutputStream fileOutputStream=null;
        try {
            fileInputStream=new FileInputStream("E:\\桌面\\桌面\\JavaCode\\java个人理解.png");
            fileOutputStream=new FileOutputStream("E:\\桌面\\桌面\\JavaCode\\java个人理解Copy.png");

            byte[] b=new byte[1024*1024];
            int data;
            while ((data=fileInputStream.read(b))!=-1){
                fileOutputStream.write(b,0,data);
            }

            fileOutputStream.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
            if (fileInputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }


    }
}

FileReader

public class FileReaderTest {
    public static void main(String[] args) {
        FileReader reader=null;
        try {
             reader=new FileReader("dd");
             char []chars=new char[4];
             int data;
             while ((data=reader.read(chars))!=-1){
                 System.out.println(new String(chars,0,data));
             }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

 FileWriter

public class FileWriterTest {
    public static void main(String[] args) {
        FileWriter fileWriter=null;
        try {
            fileWriter=new FileWriter("ff");
            char[]chars={'d','f','f','r'};
            fileWriter.write(chars);
            fileWriter.write("dsfdsgggag");
            fileWriter.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (fileWriter != null) {
                try {
                    fileWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

 BufferedReader

public class BufferedReaderTest {
    public static void main(String[] args) throws IOException {
        FileReader fileReader=new FileReader("dd");
        BufferedReader bufferedReader=new BufferedReader(fileReader);
        String s=null;
        while ((s=bufferedReader.readLine())!=null) {
            System.out.println(s);
        }
        bufferedReader.close();
    }
}

 InputStreamReader

public class InputStreamReaderTest {
    public static void main(String[] args) throws FileNotFoundException {
        FileInputStream fileInputStream=new FileInputStream("dd");
        InputStreamReader inputStreamReader=new InputStreamReader(fileInputStream);
        BufferedReader bufferedReader=new BufferedReader(inputStreamReader);
    }
}

DataOutputStream和DataInputStream


/*
DataOutputStream对数据加密,打印出来是乱码,只能用DataInputStream读
 */
public class DataOutputStreamTest {
    public static void main(String[] args) throws IOException {
        DataOutputStream dataOutputStream=new DataOutputStream(new FileOutputStream ("ss"));
        int i=100;
        dataOutputStream.writeInt(i);
        dataOutputStream.flush();
        dataOutputStream.close();

        DataInputStream dataInputStream=new DataInputStream(new FileInputStream("ss"));
        int j=dataInputStream.readInt();
        System.out.println(j);
        dataInputStream.close();


    }
}

 PrintStream

/*
PrintStream输出到控制台
 */
public class PrintStreamTest {
    public static void main(String[] args) throws FileNotFoundException {
        //联合起来写
        System.out.println("Hello");

        //分开写
        PrintStream ps=System.out;
        ps.println("hh");

        //这个不需要手动关闭

        PrintStream printStream=new PrintStream(new FileOutputStream("ff"));
        System.setOut(printStream);  //改变文件输出方向,不在输出到控制台而是输出到ff文件中
        System.out.println("fdas");
        System.out.println("hh");
    }
}

 File

/*
File 类和四大家族没有关系,所以不能完成读写
File对应的是文件的目录或者是文件
File是路径的抽象表示
 */
public class Filetest {
    public static void main(String[] args) throws IOException {
        File file=new File("E:\\file");

        System.out.println(file.exists());//判断目录或者文件是否存在false

        if (!file.exists()){  //D:\file不存在则创建一个文件
            file.createNewFile();
        }

        if (!file.exists()){//D:\file不存在则创建一个目录
            file.mkdir();
        }

        System.out.println(file.getParent());//获取文件父路径
        System.out.println(file.getAbsoluteFile());//获取绝对路径

        System.out.println(file.getName());//获取文件名

        System.out.println(file.isDirectory());//判断是否是目录

        System.out.println(file.isFile());//判断是否是文件

        long time=file.lastModified();//毫秒从1970年到现在
        Date date=new Date(time);
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        String s=simpleDateFormat.format(date);
        System.out.println(s);

        System.out.println(file.length());//获取文件大小字节
    }
}

目录复制


public class CopyAll {
    public static void main(String[] args) {
        File srcFile =new File("E:\\小黑");
        File destFile =new File("E:\\d");
        copyDir( srcFile,destFile);
    }

    /**
     * 拷贝目录
     * @param srcFile 拷贝源
     * @param destFile  拷贝目标
     */
    private static void copyDir(File srcFile, File destFile) {
        if (srcFile.isFile()){
            FileInputStream in=null;
            FileOutputStream out=null;
            try {
                in =new FileInputStream(srcFile);
                String h=(destFile.getAbsolutePath().endsWith("\\")?destFile.getAbsolutePath():destFile.getAbsolutePath()+"\\")+srcFile.getAbsolutePath().substring(3);

                out =new FileOutputStream(h);
                byte []bytes=new byte[1024*1024];
                int redcode;
                while ((redcode=in.read(bytes))!=-1){
                    out.write(bytes,0,redcode);
                }
                out.flush();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (out != null) {
                    try {
                        out.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
        File[] files= srcFile.listFiles();//源下面子目录

       
        for (File f :
                files) {
            if (f.isDirectory()){
                String srcDir=f.getAbsolutePath();
                String destDir=(destFile.getAbsolutePath().endsWith("\\")?destFile.getAbsolutePath():destFile.getAbsolutePath()+"\\")+srcDir.substring(3);
                System.out.println(destDir);
                File n=new File(destDir);
                if (!n.exists()){
                    n.mkdirs();
                }
            }
            copyDir(f,destFile);
        }

    }
}

ObjectInputStream 和ObjectOutputStream

序列化和反序列化(就是读入写出分成一小份一批一批运输),参与序列化和反序列化的对象,对象类必须实现Serializable接口(系统会自动生成一个序列号,当对象类更改了代码系统又会生成一个新的序列号,但是在读的时候是之前写的信息,系统会报错,所以必须给对象类自定义序列号private static final long serialVersionUID = 1L。java判断一个类是否相同先判断类名,然后是序列号);

注意,通过源码可以发现,Serializable接口是一个标志性接口 

public interface Serializable{

}

这个接口中什么代码都没有,他的作用起到标识的作用,java虚拟机看到这个类实现这个接口,可能对这个类实现特需待遇,自动生成序列化版本号

若不想将对象某个属性序列化可以用transient关键字修饰

 IO和Properties集合联合

public class test {
    public static void main(String[] args) throws IOException {
        FileInputStream fileInputStream=new FileInputStream("dd");
        Properties properties=new Properties();
        properties.load(fileInputStream);
        System.out.println(properties.getProperty("Account"));  //自动将=右边内容输出
        System.out.println(properties.getProperty("Password"));
        //这样设计的理念
        /*
        以后经常改变数据,可以单独写到一个文件中,使用程序驱动动态读取。
        将来只需要修改这个文件内容,java代码不需要改动,不需要重新编译,
        服务器也不需要重启,就可以拿的动态信息

        类似以上机制文件被称作配置文件
        并且配置文件中的内容格式是
        key1=value
        key2=value
        的时候,我们把这种配置文件叫做属性配置文件

        java规范中有要求:属性配置文件一.properties结尾,但不是必须 的
        

         */
    }
}

多线程

什么是进程?什么是线程?

进程是一个应用程序(一个进程是一个软件)

线程是一个进程中的执行场景/执行单元

一个进程可以启动多个线程

对于java程序来说,当DOS命令窗口输入:java HelloWord 回车之后

会先启动JVM,二JVM就是一个进程,

JVM再会启动一个垃圾回收线程负责看护,回收垃圾。

最起码,现在的java程序最起码有垃圾回收线程和一个main主函数线程

举个例子:

阿里巴巴:进程

马云:一个线程

童文红:一个线程

进程A与进程B的内存独立不共享

线程A和线程B:堆内存中和方法区内存共享,但是栈内存独立,一个线程一个栈、

假设启动10个线程就会有10个栈空间,每个栈和每个栈之间互不干扰,各自执行各自的

这就是多线程并发

思考一个问题:使用多线程之后,main方法执行结束,是不是其他线程也结束了?

main方法结束只是主栈结束,主栈空了,其他栈可能还在压栈或者弹栈

分析一个问题:对于单核CPU来说,真的可以做到多线程吗

对于单核CPU来说,由于CPU处理速度极快,线程与线程之间频繁交换给一种错觉

start()方法解释

public class test {
    public static void main(String[] args)  {
        myThread m=new myThread();
        m.run();//并不会启动多线程,只是调用方法而已

        m.start();//这里会立马在新建一个myThread栈,多线程开始

        for (int i=0;i<1000;i++){
            System.out.println("主线程执行了"+i);
        }

    }
    /*
    start()方法的作用:启动一个分支线程,在JVM开辟一个新的栈空间,执行这段代码后立马瞬间结束,
    这段代码作用是开辟新的栈空间,开辟完后就结束了
    线程成功启动会自动调用run方法,将run自动压栈,并且run方法在该栈低部
    run方法在支栈的底部,main方法在主栈的底部,这两个方法是同级的
     */
}
class myThread extends Thread{
    @Override
    public void run() {
        for (int i=0;i<1000;i++){
            System.out.println("myThread线程执行"+i);
        }
    }
}

java实现线程的两中方式

第一种:编写一个类直接继承java.lang.Thread,重写run()方法

第二种:编写一个类,实现java.lang.Runnable接口,实现run()方法

注意:第二种方法更好,他还可以继承别的类

           也可以采用内部类方式创建线程

线程生命周期获取取当前线程对象、对象名字、修改线程名字

public class test1 {
    public static void main(String[] args) {
    hh l=new hh();
    hh l2=new hh();
    l.setName("h1");//对线程对象改名
        System.out.println(l2.getName());//线程默认名字,Thread-1 ,l线程的默认名Thread-0但是该了,默认名递加
        l.start();
        l2.start();

    }
}

class hh extends Thread{
    @Override
    public void run() {
        for (int i=0;i<1000;i++){
            //Thread.currentThread()当前线程对象
            //Thread.currentThread().getName()当前线程对象的名字
            System.out.println(Thread.currentThread().getName()+i);
        }
    }
}

sleep()方法、interrupt()方法、更好的线程终止方法

public class test1 {
    public static void main(String[] args) {
        hh r=new hh();
    Thread t=new Thread(r);
    t.setName("t");
    t.start();
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

    //t.interrupt();//当main线程执行到5秒进入这个代码,终止t对象线程
                    //但是由于太过暴力可以这样
        r.newrun=false;
    }
}

class hh implements Runnable {
    boolean newrun=true;
    @Override
    public void run() {
        for (int i=0;i<10000;i++) {
            if (newrun) {

                try {
                    Thread.sleep(1000);     //当前线程,记住当前线程
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println(Thread.currentThread().getName() + i);

            } else {
                //终止当前程序
                //可以对终止前进行一些操作
                return;
            }
        }
    }
}

常见的线程调度模型

1.抢占式调度模型

         那个线程的优先级比较高,抢到的CPU时间片概率就高一些

        java就是这种模式

2.均分式调度模型

        平均分配时间片

java提供那些方法和线程调度有关

实例方法:

        void setPriority(int newPriority) 设置线程的优先级

        int getPriority() 获取线程优先级

        最低优先级1

        默认5

        最高10

        (优先级比较高的获取时间片可能会多一些,但也不完全是,大概率是高的)

实例方法:

        void join()

        合并线程

        class MyThread1 extends Thread{

public void doSome(){

MyThread2 t=new MyThread2();

t.join();//当前线程进入阻塞,让t线程先执行,直到t线程结束,当前线程才可以执行

//Thread.yield();//当前线程暂停一下个其他线程

}

}

class MyThread2 extends Thread{

}

线程安全与synchronize()

什么时候在多线程并发的环境下存在安全问题?

        1.多线程并发

        2.有共享 数据

        3.共享数据有修改行为

怎么解决?

线程排队执行(不能并发)称作线程同步机制也叫线程同步

异步编译模型

线程1,线程2,各执行各的,谁也不管谁,异步就是并发

同步

线程1在执行线程2等待直到线程1结束

class Account {
    private String account;
    private int balance;

    public Account(String account, int balance) {
        this.account = account;
        this.balance = balance;
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public int getBalance() {
        return balance;
    }

    public void setBalance(int balance) {
        this.balance = balance;
    }
    //取钱
    public void withdrawal(int withdrawalAmount){
        /*
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        balance=balance-withdrawalAmount;
        //这样是可以卡银行的bug的
         */
        /*以下代码是线程排队,不能并发
        一个线程把这里的代码全部执行玩,另一个线程才能进来
        线程同步机制语法:
        synchronize(){
        //线程同步代码块
        }
        synchronize后面小括号中传这个“数据”非常关键
        ()中写什么是要看你想同步那个线程
        这里的共享对象是:账户对象
        账户对象是共享的,那么this就是账户对象吧
        不一定是this,这里只要是多线程共享的那个对象就行

         */
        synchronized (this){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            balance=balance-withdrawalAmount;
        }
        /*
        以上代码块执行原理:
        在java语言中,然后一个对象都有“一把锁”其实这把锁就是标记
        100个对象,100个锁,一个对象一个锁
        1.假设t1和t2线程并发,开始开始执行以上代码肯定有一个先后顺序
        2.假设t1先执行了,遇到synchronize,这个时候自动找到“后面共享对象”的对象锁,
        并占用,然后执行同步代码,直到结束,才会释放
        3.假设t1占有这把锁,t2遇到synchronize关键字,他也
        会占用后面对象锁,直到t1结束t2才能执行

        这样就达到线程排队执行
        这里的共享对象一定要选好
         */
    }
}
class AccountThread extends Thread{
    private Account account;

    public AccountThread(Account account) {
        this.account = account;
    }

    @Override
    public void run() {
        account.withdrawal(5000);
        System.out.println(Thread.currentThread().getName()+ account.getAccount()+"withdrawalBalance"+account.getBalance());
    }
}

public class main{
    public static void main(String[] args) {
        Account account=new Account("act",10000);
        Thread t1=new AccountThread(account);
        Thread t2=new AccountThread(account);
        t1.setName("t1");
        t2.setName("t2");
        t1.start();
        t2.start();
    }

 

 

java三大变量与线程安全关系

实例变量:堆中,堆只有一个所以线程共享,存在线程安全问题

静态变量:方法区,方法区只有一个所以线程共享,存在线程安全问题

局部变量:栈中,局部变量部共享,一个线程一个栈,不存在安全问题

常量:不存在

成员变量:可能有

局部变量用StringBuilder,不存在线程安全其他,效率高

ArrayList非线程安全

vector线程安全

HashMap Hashset非线程安全

Hashtable线程安全

线程守护

public class test {
    public static void main(String[] args) {
        Thread t=new B();
        t.setName("t");
        //启动线程之前设置为守护线程
        t.setDaemon(true);
        t.start();
        for (int i=0;i<4;i++){
            System.out.println(Thread.currentThread().getName()+(++i));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
class B extends Thread{
    @Override
    public void run() {
        int i=0;
        while (true){
            System.out.println(Thread.currentThread().getName()+(++i));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

定时器

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class Data {
    public static void main(String[] args) throws ParseException {
        Timer t=new Timer();//创建线程守护对象
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date firstTime=sdf.parse("2023-03-17 00:14:50");
        t.schedule(new c(),firstTime,1000*5);
        //t.schedule(执行任务,第一次执行时间,间隔多久执行一次);
    }
}
class c extends TimerTask {
    @Override
    public void run() {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String srrTime=sdf.format(new Date());
        System.out.println(srrTime+"完成一次备份");
    }
}

实现线程的第三种方法

 

 

 wait()和notify()方法

 

public class test {
    public static void main(String[] args) {
        List<Integer> list=new ArrayList<>();
        Thread thread1= new Thread(new produce(list));
        Thread thread2= new Thread(new consume(list));
        thread1.setName("生产线程");
        thread2.setName("消费线程");
        thread1.start();
        thread2.start();
    }
}
//生产
class produce implements Runnable{

    private List list;

    public produce(List list) {
        this.list = list;
    }
    private int i=1;

    @Override
    public void run() {
      while (true){
          synchronized (list){
              if (list.size()>0){
                  try {
                      list.wait();
                  } catch (InterruptedException e) {
                      throw new RuntimeException(e);
                  }
              }
                list.add((i++));
              System.out.println(Thread.currentThread().getName()+list.get(0));
              list.notifyAll();
          }
      }
    }
}

//消费
class consume implements Runnable{
    private List list;

    public consume(List list) {
        this.list = list;
    }

    @Override
    public void run() {
        while (true){
            synchronized (list){
                if (list.size()==0){
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                System.out.println(Thread.currentThread().getName()+list.get(0));
                list.remove(0);
                list.notifyAll();
            }
        }
    }
}

反射机制

作用:操作字节码文件,让程序更加灵活

反射机制在java,lang.reflect.*;包下

反射机制相关的重要的类:

        java.lang.class:代表整个字节码,代表一个类型,代表一个类

        java.lang.reflect.Method:代表字节码中的方法字节码,代表类中的方法

        java.lang.reflect.Constructor:代表字节码中的构造方法字节码,代表类中的构造方法

        java.lang.reflect.Field:代表字节码中的属性字节码,代表类中的成员变量(静态变量,实例变量)

三种获取字节码文件方式

public class test
{
    public static void main(String[] args) {
        /*
        Class.forName()
        1.静态方法
        2.方法参数是字符串
        3.字符串需要一个完整的类名
        4.完整类名必须带有包名
        5.如果只想静态代码块(类加载执行)执行,可以用这个方法
         */
        Class c1=null;
        try {
             c1=Class.forName("java.lang.String");//c1代表String.class文件,或者c1代表String类型
            Class c2=Class.forName("java.util.Date");//c2代表Data类型

        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }


        /*
        java中任何一个对象都有getClass()方法
         */
        String s="sad";
        Class x=s.getClass();//x代表String字节码文件,String类型
        System.out.println(c1==x);//true,判断对象内存地址


        /*
        java中任何一种类型,都有.class属性
         */
        Class a=int.class;
        Class b=int.class;
        System.out.println(a==b);//true
    }
}

通过相对路径获取绝对路径两种方法

package Test;


import java.io.InputStream;

import java.util.Properties;

public class test
{
    public static void main(String[] args) throws Exception {
//      String path= Thread.currentThread().getContextClassLoader().getResource("hh.properties").getPath();
//        System.out.println(path);
//      FileReader fileReader=new FileReader(path);
        InputStream fileReader=Thread.currentThread().getContextClassLoader().getResourceAsStream("hh.properties");//与包名同级
        InputStream fileReader2=Thread.currentThread().getContextClassLoader().getResourceAsStream("Test/gg.properties");//与类名同级
      Properties properties=new Properties();
      properties.load(fileReader2);
      fileReader2.close();
      String name=properties.getProperty("name");
        System.out.println(name);
    }
}

java.lang.reflect.Field

package Test;

import java.lang.reflect.Field;

public class test {
    public static void main(String[] args) throws ClassNotFoundException {
    Class l=Class.forName("Test.f");
    Field[] files= l.getFields();
        System.out.println(files.length);   //1
        for (Field f:files
             ) {
            System.out.println(f.getName());  //i
        }

    Field [] fields=l.getDeclaredFields();
        System.out.println(fields.length);  //4
        for (Field f:fields
             ) {
            System.out.println(f.getName()); //i,j,k,h
        }

    }
}


package Test;

public class f {
    public int i;
    protected int j;
    private  int k;
    boolean h;
}

反射机制访问对象属性

package Test;

import java.lang.reflect.Field;

public class test {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
    Class l=Class.forName("Test.f");
    Object o= l.newInstance();
    Field field=l.getDeclaredField("i");
    field.set(o,100);
    System.out.println(field.get(o));

    Field field1=l.getDeclaredField("k");
    field1.setAccessible(true);  //打破了封装哟
    field1.set(o,66);
        System.out.println(field1.get(o));

    }
}


package Test;

public class f {
    public int i;
    protected int j;
    private  int k;
    boolean h;
}

可变长度参数

package Test;

/*
可变长度参数
语法:类型...
可变参数的个数个数是0到n个
可变参数可以当数组看待
可变参数只能有一个,并且在最后
 */
public class test {
    public static void main(String[] args) {
    h("ztj",1,2,1);

    }
    public static void h(String s,int...a){
        for (int i=0;i<a.length;i++){
            System.out.println(a[i]);
        }
    }
}

java.lang.reflect.Method

package Test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/*
可变长度参数
语法:类型...
可变参数的个数个数是0到n个
可变参数可以当数组看待
可变参数只能有一个,并且在最后
 */
public class test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
    Class l=Class.forName("Test.f");
        Method[] methods=l.getDeclaredMethods();
        System.out.println(methods.length);  //1
        for (Method m:methods
             ) {
            System.out.println(Modifier.toString(m.getModifiers()));//方法修饰类型
            System.out.println(m.getReturnType().getSimpleName());  //方法返回类型
            System.out.println(m.getName());    //  方法名
            Class[] p=m.getParameterTypes();
            for (Class par:p
                 ) {
                System.out.println(par.getSimpleName()); //  方法参数类型
            }
        }
        
        //调用方法
        Object o=l.newInstance();
        Method m=l.getDeclaredMethod("g",String.class,int.class);
        Object value=m.invoke(o,"ztj",1);
        System.out.println(value);
    }
}


package Test;

public class f {


    public void g(String s,int i){

    }
}

获取一个类的父类的接口

public class test {
    public static void main(String[] args) throws ClassNotFoundException {
    Class l=Class.forName("java.lang.String");
    Class superClass=l.getSuperclass();
        System.out.println(superClass.getName());//java.lang.Object

        Class []i=l.getInterfaces();
        for (Class h:i
             ) {
            System.out.println(h.getName());
            /*
java.io.Serializable
java.lang.Comparable
java.lang.CharSequence
java.lang.constant.Constable
java.lang.constant.ConstantDesc
             */
        }

    }
}

注解

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值