java笔记

一、java"一次编译,到处运行"的跨平台性:

跨平台的原因:
同样的一个java字节码文件(.class),既可以在java CPU上运行,也可以通过Windows的
java字节码解释程序,(就像一个虚拟的java CPU,也就是JVM(java虚拟机)),进行解释运行
只要操作系统上有相应的java字节码解释程序,.class文件就能在这个操作系统上编译运行,
不是所有的操作系统都有字节码解释程序!

二、堆和栈内存?

  • java将内存划分为堆内存和栈内存,定义的变量是存放在栈内存中的 ,而new出来的对象和数组是存放在堆中的
  • 栈内存:当一个函数调用时,会在栈内存中申请一个空间,当函数中定义一个变量时,会分配到这个函数申请的栈空间中
    ,函数运行结束时,函数的栈空间被收回,在这个函数中定义的变量也随之被收回
  • 堆内存:用new关键字产生的数组和对象都存放在堆内存中,由java的垃圾回收器来自动管理,堆中产生一个数组或对象,
    ,还可以在栈中定义一个"引用变量",取值等于堆中的数组或对象的首地址,以后就可以直接通过栈中的引用变量
    ,直接调用在堆中的数组或对象,栈中的这个变量就是堆中对象或数组的别称,或者是代号
  • 引用变量是一个普通变量,第一次在栈中分配,当超过他的作用域之外就会被回收,而堆中的对象或数组,即使不使用,方法结束
    也不会释放,只是没有引用变量指向他的首地址了,变成垃圾,不能使用,但是依然站着堆内存空间不放, 到最后被垃圾回收器回收走 这就是java比较消耗内存的原因


    堆和栈内存
public class Arraylist_demo {
    public static void main(String[] args) {
        // 定义了一个普通变量,其中要装的数据是堆中某个对象的首地址
        int[] x;
        // 在堆内存中产生了一个数组,将首地址赋值给x
        x = new int[5];

        int sum = 0;
        for (int i = 0; i < x.length; i++) {
            x[i] = i + 1;
            sum += x[i];
        }

        // x变量中的值设为null,x就与原先的数组对象断开了关系,原来的数组对象就没有任何引用变量指向它,然后他就等待垃圾回收器来将它释放
        x = null;
        System.out.println(sum);

        // 静态数组,定义时就赋值
        // ! int[5], 不能指定长度 !

        int[] arr = new int[] { 1, 2, 3, 4, 5 };

        // arr = null;
        // java.lang.NullPointerException空指针异常:
        // 使用时如一个函数返回一个对象,使用时判空,不让经常导致空指针异常

        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
        // java.lang.ArrayIndexOutOfBoundsException数组下标越界
        // System.out.println(arr[5]); 角标大于最大角标
        // 防止异常使用length
        System.out.println("最后一个数为:" + arr[arr.length - 1]);

        /**
         * 多维数组:
         * 
         * 类似棋盘
         */

        int[][] xx = new int[2][3];
        xx[0][0] = 5;
        xx[1][2] = 8;
        for (int i = 0; i < xx.length; i++) {
            for (int j = 0; j < xx[i].length; j++) {
                System.out.println("xx[" + i + "][" + j + "]" + xx[i][j]);
            }
        }

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

        /**
         * arraycopy
         */
        int[] aa = new int[] { 2, 3, 1, 5, 9 };
        int[] bb = new int[10];
        System.arraycopy(aa, 0, bb, 2, aa.length);

        for (int i = 0; i < bb.length; i++) {
            System.out.println("bb[" + i + "]:" + bb[i]);
        }
    }
}

三、java和Android的区别:

java内涵:
1、一种编程语言
2、一套开发工具
3、一个运行环境
Android是:
具体的操作系统,可以用java语言来编写

四、面向对象

java中的对象:万物皆对象,指的是现实中存在的具体实例;
·面向过程:
    [主 '谓' 宾]重点在谓语,怎么操作?
·面向对象
    ['主' 谓宾]重点是主语,操作谁?
·三大特征
    封装 继承 多态
·核心
    类与对象
    {类:是对一种事物的描述,是抽象的,概念上的定义        -动物     ***
    {对象:是实际存在的某个该类事务的个体,也称为实例       -猫,狗
    
private私有的  public公开的
    
四.1:类   
    一个类就是一个小的模块,尽可能的只公开必须让外部知道的内容,隐藏其他一切内容
    设计时避免一个类直接修改另一个类的数据
    模块设计:
        强内聚:许多功能尽量在类的内部独立完成,不让外面干预
        弱耦合:给外部尽可能少的方法调用
        
四.2:this关键字
    - 一个类中的成员方法可以直接调用同类中的其他成员
    - 让该类的成员变量名和对其赋值的成员方法的形参变量同名
    
四.3:垃圾回收
    System.gc(); - 叫来垃圾回收器

五、static

静态对象被所有的实例对象所共享
属性作用域
方法中可以访问属性,但方法之间不能访问彼此内部定义的变量
  • 静态方法

使用前不用创建任何对象

main方法是静态的,JVM在执行main方法时不创建main方法所在的类的实例对象,所以不能直接访问该类的非静态成员,必须创建该类的一个实例对象,才能通过这个对象去调用非静态成员

  • 静态变量

特定的数据在内存中只有一份,无论是否产生,或产生了多少对象;

  • 静态代码块:

一个类可以中可以使用不包含在任何方法中的静态代码块,类被载入时,静态代码块执行,且执行一次,常作属性初始化操作。

即使产生多个实例对象,其中静态代码块只执行一次

当一个程序中用到了其他的类,类是在第一次被使用的时候才被装载,而不是在程序启动时就加载程序中的所有用到的类

  • 子类对象实例化 : new关键字

六、多线程

六.1:进程
    在多任务的系统中,每个独立执行的程序都被称为进程(正在进行的程序)
    CPU只有一个的情况下,每个进程之间要不断的切换,反而要额外的开销(交替执行多个程序)反而更慢
    双CPU系统才能实现多进程,每个CPU一个执行一个程序,两个程序同时进行
    一个进程可以包含一个或多个线程
六.2:线程
    一个线程就是一个程序内部的一条执行线索
    多线程:一个程序实现多段代码同时交替运行,就需要产生多个线程,并且指定每个线程要执行的代码   
    Thread.currentThread().getName();
    
    Thread thread = new Thread();
    //后台线程
    thread.setDaemon(true);
  • 多线程卖票案例
public class ThreadDemo {
    public static void main(String[] args) {
        try {
            /**
             * 一个thread对象是一个线程
             */
            TestThread tt = new TestThread();
            // 继承thread
            // tt.start();
            // tt.start();
            // tt.start();
            // tt.start();

            new Thread(tt).start();
            new Thread(tt).start();
            new Thread(tt).start();
            new Thread(tt).start();
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
}

/**
 * 实现runnable 接口比继承thread灵活
 * 
 * 适合多个相同程序代码的线程去处理同一资源的情况,把虚拟CPU(线程)同程序代码、数据有效分离 , 体现了面向对象的设计思想
 * 
 * @author TianYu
 *
 */
class TestThread implements Runnable /* extends Thread */ {
    int tickets = 100;

    @Override
    public void run() {
        while (true) {
            if (tickets > 0) {
                System.out.println(Thread.currentThread().getName() + "  is show " + tickets--);
            }
        }
    }
}

基础

① if & switch

/**
 * 使用{}使得代码可读性好
 * 
 * @author TianYu
 *
 */
public class If_demo {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入数字");
        int i = scanner.nextInt();

        /**
         * if语句 执行多条语句要放在{}中的代码块中
         * 
         * 每个语句可以是使用{}组成的复合语句
         */
        if (i < 3) {
            System.out.println("输入的数字<3");
        } else if (i >= 3 && i <= 8) {
            System.out.println("输入的数字在3和8之间");
        } else {
            System.out.println("输入的数字>8");
        }

        /**
         * 
         * 三元运算符 当语句比较简单,使用问号表达式: 条件成立执行:前,否则执行:后语句
         * 
         * 变量 = 布尔表达式 ? 语句1 :语句2
         */
        System.out.println("--------------------------------");
        int y;
        y = i >= 5 ? i : -i;
        System.out.println(y);

        /**
         * syitch语句:
         * 
         * 只要找到一个case语句就开始执行,所以拿break跳出switch代码,执行之后代码 int byte char short
         * 不能接受其他类型
         */
        System.out.println("--------------------------------");
        switch (i) {
        case 1:
            System.out.println("你输入的是一");
            break;
        case 2:
            System.out.println("你输入的是二");
            break;
        case 3:
        case 4:
            System.out.println("3,4");
            break;
        default:
            System.out.println("你输入的大于二");
            break;
        }

        while (i <= 10) {
            System.out.println(i++);
        }
    }
}

② Float

public class Float_demo {
    public static void main(String[] args) {
        // 最大浮点数 Infinity 幂指数为254 有效的
        System.out.println(Float.intBitsToFloat(0X7f800000));
        // 比最大还大 NaN 幂指数为255
        System.out.println(Float.intBitsToFloat(0X7f800001));
        // 最小浮点数
        System.out.println(Float.intBitsToFloat(0X00000001));

        System.out.println(Float.intBitsToFloat(0X50000000));

        /**
         * 区间 
         */
        Float x = 3.141f;
        if (x > 3.14 || x < 3.15) {
            System.out.println(x);
        } else {
            System.out.println("x不在此区间");
        }
    }
}

七、File

  • file类

file类是io包中唯一代表磁盘文件本身信息的类,而不是文件的内容

创建-删除-重命名

list方法可以返回目录中所有子目录和文件名

Java文件类以抽象的方式代表文件和目录(文件夹)路径名

1)属性:
    static String separator 与系统有关的默认名称分隔符 

2)构造方法
    File(File parent, String child) 
        根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。 
    File(String pathname) 
        通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。 
    File(String parent, String child) 
        根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
      
3)普通方法
    1.创建的方法:
        1.boolean createNewFile() 不存在返回true 存在返回false
        //2.boolean mkdir() 创建目录
        3.boolean mkdirs() 创建多级目录  ,也可以创建一个文件目录
    2.删除的方法:
        1.boolean delete()
    3.重命名功能 ,还能实现剪切
        public boolean renameTo(File dest)
    4.判断功能
        public boolean isDirectory() 是文件目录
        public boolean isFile()  是文件
        public boolean exists()  存在
    5.基本获取
        public String getPath() 获得路径
        public String getName() 获得文件名
        public long length()     获得文件大小
        File getParentFile() 返回此抽象路径名父目录的抽象路径名;如果此路径名没有指定父目录,则返回 null。 
        File[] listFiles() 返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
/**
 * @date:2020/6/30
 * @describe:文件
 * @author:TianYu
 */
public class FileTest {
    public static void main(String[] args) {
        try {
            final File file = new File("1.txt");
            if (file.exists()) {
                //如果存在就删除
                file.delete();
            } else {
                //创建
                file.createNewFile();
            }

            System.out.println("file name : " + file.getName());//文件名
            System.out.println("file path : " + file.getPath());//文件路径
            System.out.println("file abs path : " + file.getAbsolutePath());//绝对路径
            System.out.println("file parent : " + file.getParent());//目录
            System.out.println(file.exists() ? "存在" : "不存在");//是否存在
            System.out.println(file.canRead() ? "read" : "not read");//是否能读
            System.out.println(file.canWrite() ? "write" : "not write");//是否能写
            System.out.println(file.isDirectory() ? "是目录" : "not 目录");
            System.out.println(file.length());
            System.out.println(new Date(file.lastModified()));//修改时间
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • RandomAccessFile类

提供了访问文件的方法

支持 '随机访问':可以跳转到文件的任意位置读写数据

"指示器"

适合随机读写等长记录格式的文件

仅限于操作文件,不能访问其他的io设备,如网络 内存印象等

  • 两种构造方式
new RandomAccessFile(file, "rw");//读写方式
new RandomAccessFile(file,"r");//只读方式
Demo:往文件中写入三名员工的信息,每个员工有姓名年龄,按照2,3,1的顺序读出信息
public class RandomFileTest {
    public static void main(String[] args) {
        Person person1 = new Person("张三", 81);
        Person person2 = new Person("李四", 98);
        Person person3 = new Person("王五", 10);

        try {
            //读写rw
            RandomAccessFile rw = new RandomAccessFile("person.txt", "rw");
            rw.write(person1.getName().getBytes());
            rw.writeInt(person1.getAge());
            rw.write(person2.getName().getBytes());
            rw.writeInt(person2.getAge());
            rw.write(person3.getName().getBytes());
            rw.writeInt(person3.getAge());

            int len = 0;
            String name = null;

            //第二个员工
            rw.skipBytes(9);
            byte[] bytes = new byte[8];

            len = rw.read(bytes);
            name = new String(bytes, 0, len);
            System.out.println(name.trim() + " : " + rw.read());

            //定位到文件的开头处
            rw.seek(0);
            len = rw.read(bytes);
            name = new String(bytes, 0, len);
            System.out.println(name.trim() + " : " + rw.read());

            rw.skipBytes(9);
            len = rw.read(bytes);
            name = new String(bytes, 0, len);
            System.out.println(name.trim() + " : " + rw.read());

            //关闭资源
            rw.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

八、节点流

流就是字节序列的抽象概念

文件是数据的静态存储形式,而流是数据传输时的形态

八.1、IO流

I:input 输入
O:output 输出

八.2、流分类

2.1按照数据流向:
    输入流:只能从中读取数据。
    输出流:只能向其写入数据。
2.2按照操作数据大小:
    字节流 
    字符流

八.3、字节流

抽象父类:
InputStream 
OutputStream

八.4、文件字节流

FileInputStream
FileOutputStream

八.5、构造方法

FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流。
FileInputStream(String name) 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。

八.6、普通方法

void write(byte[] b) 将 b.length 个字节从指定 byte 数组写入此文件输出流中。 
void write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。 
void close()关闭此文件输出流并释放与此流有关的所有系统资源。 
int read(byte[] b) 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。 
int read(byte[] b, int off, int len) 从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。 
void close() 关闭此文件输入流并释放与此流有关的所有系统资源。 

八.7、文本文件结束,通过read方法读取时,如果返回的是-1,即到了文件结尾;

八.8、字符流父类

Reader 输入流
Writer 输出

八.9、文件字符流

FileWriter
FileReader

八.10、文件复制注意事项

如果复制的文件是完整数据如:视频,图片,压缩包 必须使用字节流;
如果是文本文件,除了字节流外还可以使用字符流; 

八.11、字符缓冲流

BufferedWriter
BufferedReader
readLine() 读取文本中一行数据   //以换行符作为一行文本结束标记

八.12、释放资源原则

后用的先关闭

九、异常

九.1、异常:代码在编译或运行时的不正常状态;

九.2、异常分类:

Throwable
     --Error 错误 通过代码很难处理的问题
     --Exception 异常 通过代码可以屏蔽的问题

九.3、异常处理

1)try...catch...finally处理方式 
try:尝试
catch:捕获
finally:放一定会被执行的代码
2)throws 抛出 写在方法体上
3)throw 抛出 写在方法内部

throws和throw的区别
throws
    用在方法声明后面,跟的是异常类名
    可以跟多个异常类名,用逗号隔开
    表示抛出异常,由该方法的调用者来处理
    throws表示出现异常的一种可能性,并不一定会发生这些异常
throw
    用在方法体内,跟的是异常对象名
    只能抛出一个异常对象名
    表示抛出异常,由方法体内的语句处理
    throw则是抛出了异常,执行throw则一定抛出了某种异常

4)异常注意事项
1:能明确的尽量明确,不要用大的来处理。
2:平级关系的异常谁前谁后无所谓,如果出现了子父关系,父必须在后面。
子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。(父亲坏了,儿子不能比父亲更坏)
如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容