Java:基本概念总结
概述
1991年由sun公司开发的语言。
JDK:Java Development Kit,Java的开发和运行环境,Java的开发工具和JRE。
JRE:Java Runtime Environment,Java程序的运行环境,Java运行的所需的类库和JVM(Java虚拟机)。
Java常用命令:javac 是负责编译的部分,当执行javac时,会启动java的编译器程序。对指定扩展名的.java文件进行编译,生成了jvm可以识别的字节码文件,即class文件,也就是java的运行程序。java 负责运行的部分,会启动jvm加载运行时所需的类库,并对class文件进行执行。一个文件要被执行,必须要有一个执行的起始点,这个起始点就是main函数。
语法基础
常量:在程序执行过程中,其值不可发生改变的量。
变量:程序执行过程中,其值可以发生改变的量,本质上来讲,变量其实是内存中一小块区域。
数据度量单位:比特(位),bit 是计算机晶体管的一种状态(通电与断电)就是0与1,真与假,是计算机最基本的传输单位,通常用小写字母 b 表示;字节 Byte 是计算机信息技术用于计量存储容量的一种计量单位,通常用大写字母 B 表示,1B = 8bit ,1KB = 1024 B;字符 一个字符是一个单位的字形、类字形单位或符号的基本信息,UTF-8编码中,一个英文字母占1B,一个汉字占3-4B。
数据类型:基本数据类型(四类八种) 引用数据类型(数组 类 接口)
基本数据类型:整数 byte short int long 小数 float double 字符 char 布尔 boolean,所占字节数分别为 1 2 4 8 4 8 2 1
引用数据类型:数组 存储同一类型多个元素的容器。数组既可以存储基本数据类型,也可以存储引用数据类型。数组需要先初始化然后才能使用。初始化就是为数组中的元素分配内存空间,并为每个元素赋值。
数组定义格式:格式1 数据类型[ ] 数组名(推荐)格式2 数据类型 数组名[ ]
二维数组:上面说的是一维数组,二维数组其实就是元素为一维数组的数组。二维数组定义格式:数组类型[ ] [ ] (推荐)
Java语言是强类型语言,对于每一种数据都定义了明确的具体数据类型,在内存中分配了不同大小的内存空间。
数据类型转换:隐式数据类型转换,取值范围小的数据类型与取值范围大的数据类型进行运算,会先将小的数据类型提升为大的,再运算;强制类型转换,需要注意如果超出被赋值的数据范围可能会与期望结果不同。
运算符:对常量和变量进行操作的符号称为运算符。常用运算符有 算术运算符 赋值运算符 关系运算符 逻辑运算符 三元运算符。
程序的流程控制:顺序 选择(if switch) 循环 ( for while )
方法:完成特定功能的代码块,在其他语言中被称为函数。
Java程序在运行时,需要在内存中分配空间,为了提高效率,就对数据进行了不同的空间划分,具体分为5种内存空间:
寄存器(程序计数器):保证线程切换后能恢复到原来的执行位置;
本地方法区:为虚拟机执行使用到的Native方法服务;
栈(虚拟机栈):存储的都是局部变量,方法被调用时,创建栈帧,只要数据运算完成所在的区域结束,该数据就会被释放;
堆:用于存储数组和对象,也就是实体。每个实体都有内存首地址值,堆内存中的变量都有默认初始化值,因为数据类型不同,值也不一样;
方法区:存储被虚拟机加载的类信息,常量,静态常量,静态方法等。(参考文档https://www.cnblogs.com/LoganChen/p/6824366.html)
面向对象
面向对象的三大特性:封装 继承 多态。
多态:父类的引用变量指向子类对象。
关键字 static 是一个修饰符,用于修饰成员(成员变量和成员函数)。特点:可以实现对象中的共性数据的对象共享,被静态修饰的成员可以直接被类名所调用,静态随着类的加载而加载。静态方法只能访问静态成员,不可以访问非静态成员,原因是静态方法加载时,优先于对象,所以无法访问对象中的成员。静态方法中不能使用this super关键字,因为this代表对象,而静态在时,有可能没有对象,所以this无法使用。主函数是静态的。
成员变量和静态变量的区别:成员变量属于对象,也称实例变量;静态变量属于类,也称为类变量;成员变量存在于堆内存中;静态变量存在方法区中;成员变量随着对象创建而存在,随着对象被回收而消失;静态变量随着类加载而存在,随着类的消失而消失;成员变量只能被对象所调用,静态变量可以被对象调用,也可以被类名调用。所以,成员变量可以称为对象的特有数据,静态变量称为对象的共享数据。静态的生命周期很长。
静态代码块:就是一个有静态关键字标示的一个代码块区域。定义在类中。可以完成类的初始化,静态代码块随着类的加载而执行,而且只执行一次(new多个对象时就只执行一次),如果和主函数在同一类,优先于主函数执行。
静态代码块、构造代码块、构造函数同时存在时的执行顺序:静态代码块 〉 构造代码块 〉 构造函数。
继承中构造方法的执行顺序:在子类构造方法第一行如果没有调用父类构造方法或没有调用子类的其他构造方法,则默认调用子类无参构造方法。因为需要给成员变量初始化。
关键字 final 是一个修饰符,可以修饰类(修饰后不可以被继承)、变量(修饰后是一个常量,只能赋值一次)、方法(不可以被重载)。
内部类:直接将A类定义在B类中,A类就称为内部类。内部类可以直接访问外部类的成员,而外部类想要访问内部类,必须要建立内部类对象。
匿名内部类:没有名字的内部类,就是内部类的简化形式。一般只用一次就可以用这种形式。匿名内部类其实就是一个匿名之类对象。想要定义匿名内部类:内部类必须继承一个类或者实现接口。
匿名内部类的格式:new 父类名或接口名 ( ) { 定义之类成员或者覆盖父类方法 }.方法名( );
抽象方法:抽取方法声明,不抽取方法主体,且方法被 abstract 修饰。
抽象类:有抽象方法的类称为抽象类。
抽象类的特点:抽象方法只能在抽象类中;抽象类不能被实例化;抽象类中可以有抽象方法;抽象类如果被继承那么其子类要么重写父类所有抽象方法要么子类也是抽象类。
接口:接口是功能的集合,同样可看成是一种数据类型,是比抽象类更抽象的类。用关键字 interface 定义。
接口中变量:接口中也可以定义变量,但是变量必须由固定的修饰符修饰,public static final 所以接口中的变量也称为常量,其值不能改变。
包:Java 中的包,类似电脑系统中的文件夹,包里存放的是类文件。
异常
异常:程序在运行时候发生的问题就是异常。在 Java 中,将异常信息封装成了一个类。当出现问题时,就会创建异常类对象并抛出异常相关的信息(异常出现的原因 位置等)。
Throwable 是 Java 语言中所有异常或错误的超类。
Error:错误,需要修正程序解决;Exception:异常,可以有针对性处理方式。
RuntimeException:是在 JVM 正常运行期间抛出的异常超类, 它及它子类只能在 Java 程序运行过程中出现。
如果出现异常没有处理,JVM 会帮我们进行处理,它会把异常的类型 原因 位置 显示在命令行并终止程序,异常后面的代码将不再执行。
编译时异常和运行时异常:编译时异常是 Exception 子类,非 RuntimeException 子类,在编译时期必须处理。运行时异常是 RuntimeException 和它的所有子类异常。
运行时异常的特点:方法中抛出运行时异常时,方法定义中无需 throws 声明,调用者也无需处理异常。
字符串
Java中,字符串一但被初始化,就不可以被改变,存放在方法区的常量池中,字符串的本质是一个字符数组。
StringBuffer 字符串缓冲区:构造一个其中不带字符的字符串缓冲区,初始容量为16个字符char,是一个长度可变的且可以存储任意类型数据的容器,since 1.0。
StringBuilder 字符串缓冲区:和StringBuffer类似,用在字符串缓冲区被单个线程是用的时候,二者区别,StringBuilder效率高,线程不安全,since 1.6。
一旦一个 String 对象在内存(堆)中被创建出来,它就无法被修改。String 类的所有方法都没有改变字符串本身的值,都是返回了一个新的对象。
如果你需要一个可修改的字符串,应该使用 StringBuffer 或者 StringBuilder。否则会有大量时间浪费在垃圾回收上,因为每次试图修改都有新的 String 对象被创建出来。
对于 String s = "a" + 变量 这样的可以用 StringBuilder 的 append() 方法替代,最后调用 toString() 方法(底层就是一个 new String())。
集合
集合是用于存储数据的容器。
集合和数组的区别:数组固定长度,集合可变长度;数组可以存储基本数据类型 或 引用数据类型,集合只能存储引用数据类型。
数据结构:就是容器中存储数据的方式。
泛型:参数化类型,即将类型由原来的具体化类型参数化,类似于方法中的变量参数。
Collection :List 有序(ArrayList LinkedList Vector) 和 Set 无序(HashSet LinkedHashSet TreeSet)。
Iterator 迭代器:是一个接口,作用:用于取集合中的元素。
Map:
Hashtable: 底层是哈希表数据结构,线程安全,不可存 null 键 null 值, since 1.0;
HashMap:底层是哈希表数据结构,线程不安全,不可以存 null 键 null 值, since 1.2;
TreeMap:底层是二叉树结构,可以对Map集合中的键进行指定顺序的排序, since 1.2。
IO流
流可以理解为数据的流动,就是一个数据流。IO流最终要以对象来体现,对象都存在IO包中。
流的分类:输入流和输出流;因处理的数据不同又可以分为字节流和字符流。
字节流:处理字节数据的流对象。设备上的数据无论是图片或者dvd,文字,它们都以二进制存储的。二进制的最终都是以一个8位为数据单元进行体现,所以计算机中的最小数据单元就是字节。意味着,字节流可以处理设备上的所有数据,所以字节流一样可以处理字符数据。
那么为什么要有字符流呢?因为字符每个国家都不一样,所以涉及到了字符编码问题,那么GBK编码的中文用unicode编码解析是有问题的,所以需要获取中文字节数据的同时指定的编码表才可以解析正确数据。为了方便于文字的解析,所以将字节流和编码表封装成对象,这个对象就是字符流。只要操作字符数据,优先考虑使用字符流体系。
流的体系因为功能不同,但是有共性内容,不断抽取,形成继承体系。该体系一共有四个基类,而且都是抽象类。
字节流:InputStream OutputStream 字符流:Reader Writer
在这四个系统中,它们的子类,都有一个共性特点:子类名后缀都是父类名,前缀名都是这个子类的功能名称。
close( )和flush( )的区别:
flush( ):将缓冲区的数据刷到目的地中后,流可以使用。
close( ):将缓冲区的数据刷到目的地中后,流就关闭了,该方法主要用于结束调用的底层资源。这个动作一定做。
线程
进程:正在进行中的程序。其实进程就是一个应用程序运行时的内存分配空间。
线程:进程中一个程序执行控制单元,一条执行路径。进程负责的是应用程序的空间标示,线程负责的是应用程序的执行顺序。
随机性原理:因为cpu的快速切换,哪个线程获取到了cpu的执行权,哪个线程就执行。
线程的五种状态:
新建状态(New):线程对象被创建;
就绪状态(Runnable):可执行状态,随时可被cpu调度执行;
运行状态(Running):线程获取cpu权限进行执行;
阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃cpu使用权,暂时停止运行,直到线程进入就绪状态,才有机会转到运行状态;
消亡状态(Dead):线程执行完成了或者因异常退出了run()方法,该线程结束生命周期。
设计模式
单例:保证一个类在内存中的对象唯一性。
单例的其中两种创建方式:饿汉式 私有化构造函数,创建私有并静态的本类对象,定义公有并静态的方法,返回该对象;懒汉式 延迟加载方式
拓展阅读: