JavaSE基础知识总结

这篇文章是当初我培训javaSE时自己在学习的过程中的总结,当然对于文章内容自己所写的并不详细,当时只是把自己感觉不熟悉的地方做个总结,无论怎样也有个复习的作用,另外我推荐学习的过程中一定要勤做总结,善于思考。

JVM包含的细节:指令集 寄存器(和cpu有关的) 类文件的格式 栈 垃圾回收堆 存储区。

JDK在安装时为什么一般不装公共JRE:公共JRE会单独安装在系统的其他路径下,会向IE浏览器和系统中注册java运行时的环境。通过这种方式系统中任何应用程序都可以使用公共JRE,由于现在在网页上执行Applet的机会越来越少,而且完全可以选择JDK下的JRE来运行java程序,因此没必要安装。

JDK的bin路径下的javac.exe命令实际上仅仅包装了这个java类,不仅如此,bin路径下的绝大部分命令都是包装了tools.jar文件里的文具类。
java编译文件只需要指定存放目标文件的位置即可,无需指定存放字节码的位置,因为javac编译时会自动生成以源文件的类的字母作为主文件名,以.class作为后缀名,如果一个源文件中有多个类,则会生成多个字节码文件。如果使用jdk1.5以上的版本完全不用设置classpath,照样正常编译和运行java程序。

java是一种纯粹的面向对象的程序语言,因此java程序必须以类(class)的形式存在,类(class)是java程序的最小单位。

定义一个32位的二进制数,其中最高位表示符号位,如果是1的话表示是一个负数,负数在计算机里以补码的形式存在,反码是原码除了最高位(符号位)不变外其他全部取反,反码加1得到补码;因此计算原码就要以此得出反码,补码。当然需要计算补码的是负数,正数的补码还是原码。

只有浮点数除以0才可以得到正无穷大或负无穷大,因为java语言会自动把和浮点运算的0(整数)当成0.0(浮点数)处理。如果一个整数值除以0,则会抛出一个异常:ArithmeticExcception:/by zero(除以0异常)。

当把任何基本类型的值和字符串值进行连接运算时,基本类型的值将自动类型转换成字符串类型,显然字符串类型不是基本类型,而是引用类型。因此如果把基本类型的值转换为对应的字符串时,可以把基本类型的值和一个空字符串进行连接。

二进制以0b开头,TB EB ZB YB BB,存储的最小单位是字节(Byte).

被java赋予了特殊含义的,被保留的,不能随意改变的字符叫关键字;java还提供了特殊的三个直接量(不是关键字):true,false,null,当然这三个也是不能用作标识符的.

char类型占2字节,取值范围是:0-65535.

for(初始化表达式@1;布尔表达式@2;步进表达式@4){条件判断语句@3; }
for 和 while 循环初始化表达式可以定义在外面,出了循环体后仍可以继续使用.

ASCII码:其中a是97,A是65,0是48.

byte short char 类型数在进行运算时,直接转换成int类型计算.

Arrays.toString(arr);输出数组字符串[…]

String 虽然是引用型类型,但是作为方法参数传递的时候,效果和基本数据类型是一致的,基本数据类型作为方法传递的时候,方法的形参的改变不会影响实际参数.

匿名对象(创建对象时没有左边的部分)只能使用唯一的一次,下次使用不得不创建一个新的对象,用于只使用一次的情况下.

泛型:也就是装在集合当中的所有元素,全都是统一的类型.可以在类中或方法中预知使用未知的类型.
泛型的好处:
A:约定了集合存储数据的数据类型;泛型给定什么类型,集合中只能存储 对应数据的数据类型.
B:将运行时期的异常提升到编译时期.
C:省去了类型转换的麻烦.
注意:泛型都是引用型类型,不能是基本的类型.

对于ArrayList集合来说,直接打印的不是地制值,而是内容.如果内容为空得到的是:[]

基本类型的泛型:int==>Integer char==>Character 其他都是首字母大写

字符串的特点: 1 字符串的内容固定不变. 2 字符串的内容可以被共享使用. 3 字符串的底层依赖的是字符数组,而字符数组依赖的是字节数组.

jdk1.7版本之前字符串常量池储存在方法区中,从jdk1.7版本之后字符串常量池储存在堆内存中.

String substring(int start,int end);截取索引从开始到结束的字符串,其中不包括结束索引处的字符.

静态的特点:被static关键字所修饰,是属于类的。
能直接被类名所调用
能被类中的所有对象所共享
总是优先于对象存在

静态的成员方法一般都用于工具类,工具类的方法都是静态的。
静态代码块:当类第一次运行时,就会执行静态代码块,而且仅执行一次,静 态代码块总会优先于构造方法而执行.

继承的好处与弊端
好处:继承能提高代码的复用性
可以提高代码的可维护性
弊端:耦合性太强,类于类之间的联系太紧密,修改了父类,子类也会更改.
因此,我们程序员的开发原则:低耦合,高内聚.

接口的总结:
成员变量是常量,格式:
[public] [static] [final] 数据类型 常量名称 = 数据值;
常量必须进行赋值,而且一旦赋值就无法更改.
其中常量名称应全部大写,可有下划线分隔.[]:表示可以省略不写
接口中最重要的是抽象方法,格式:
[public] [abstract] 返回值类型 方法名称(参数列表);
注意:实现类必须覆盖重写接口中的所有抽象方法,除非实现类是抽象类
从java8开始,接口允许定义默认方法,格式:
[public] default 返回值类型 方法名(参数列表){方法体}
注意:默认方法也可以被覆盖重写.
从java8开始,接口允许定义静态方法,格式:
[public] static 返回值类型 方法名(参数列表){方法体}
注意:应该通过接口名称进行调用,不能通过实现类对象调用接口静态方 法,因为接口本来就不能创建对象.
从java9开始,接口中可以定义私有方法,格式:
普通私有方法:private 返回值类型 方法名(参数列表){方法体}
静态私有方法:private static 返回值类型 方法名(参数列表){方法体}
注意:private的方法只有接口自己调用,不能被实现类或别人使用.

类、接口的关系区别:
类与类:继承关系,只支持单继承,不支持多继承,但可以多层继承
类与接口:实现关系,可以单实现,也可以多实现,类还可以在继承一个类的 同时在实现多个接口,首先要先继承.但是接口不能继承一个类.
接口与接口:继承关系,可以单继承也可以多继承.

抽象类完成的是一些共性的功能,也就是共性抽取;
接口完成的是一些特性的功能,也就是特性抽取.

多态中成员的访问特点:
成员方法:编译看左边,运行看右边.
成员变量:编译看左边,运行看左边.
静态方法:编译看左边,运行看左边.

abstract不能和那些关键字一起使用:
1 final:final表示最终的,是不能被覆盖重写的,而abstract修饰的方法一 定要进行覆盖重写才能够使用.
2 private:表示私人的,是不能被其他类使用的,而抽象方法是要子类中进行 覆盖重写的.
3 static:表示静态的,能被类名直接调用,而abstract修饰的方法是没有具 体的内容,如果被类名调用是没有意义的.

内部类:内部类可以访问外部类中的所有成员.
使用方式:外部类名.内部类名 对象名 = new 外部类对象().内部类对象();
注意事项:局部内部类,如果希望访问所在方法的局部变量,那么这个变量必 须是有效final的.

备注:从java8开始,只要局部变量事实不变,那么final关键字可以省略.
原因:new出来的对象在堆内存中,而局部变量在栈内存中,局部变量随着方 法的出栈而结束,而对象会一直存在,直到垃圾回收机制回收掉,所以可能导 致局部变量不存在了而对象还在,这就需要使用final来保证局部变量的使用.

类的权限修饰符的使用:
外部类:public 默认的
成员内部类:public protected 默认的 private
局部内部类:什么都不写,和局部变量相似没有权限修饰符,因为添加权限修 饰符是没有意义的,它只在局部中才有用.

方法覆盖重写的原则:应遵循”两同两小一大”的原则,两同指的是方法名相同,参数列表相同;两小指的是子类方法返回值类型小于或等于父类方法的返回值类型,子类方法声明抛出的异常类应比父类声明抛出的异常更小或相等;一大指的是子类方法的访问权限应大于或等于父类方法的访问权限.

当使用实例来访问类成员时,实际上依然是委托该类来访问类成员,因此即使这个实例为null,它仍可以访问它所属的类成员.但是如果一个null对象访问实例成员时将会发生NullPointerException异常,因为null表明该实例不存在,既然实例不存在,那么它的实例变量和实例方法自然也不存在.

Calendar类:
Calendar类是抽象类,所以无法创建对象使用,要调用其本类的静态方法.
Calendar c = Calendar.getInstance();
c.setTime(Date date);可以把Date类型数据设置进Calendar中.

如果需要输出固定长度的数据,不一定用switch语句,也可以把这些数据存入数组中,然后遍历数组,输出需要的索引值.

System.exit(1);退出jvm,可以结束整个方法,此时等效于return.

迭代器:
获取迭代器的对象需要调用方法:Iterator it = 集合对象.iterator();
成员方法: void remove();
使用迭代器的注意事项:
出现的异常:NoSuchElementException:获取不到下一个元素了
出现的原因:多调用了一次next()方法
解决的方式:通过循环来判断是否有元素,如果有再获取;如果 没有则循环结束.

ConcurrentModificationException:并发修改异常
出现的原因:通过迭代器进行遍历集合的同时,使用集合自身的 方法对集合元素进行删除,此时迭代器中的元素个数和集合的元 素个数匹配不上.
解决的方式:使用迭代器本身的remove()方法进行删除.

数组结构:
数组结构特点:查询快(有索引,可以快速定位元素)、增删慢(如果向数组 中增加或删除元素需要重新建立新的数组).

ArrayList集合:长度是可变的;底层也是数组实现;创建集合对象时,开 辟了一个长度为10的数组空间,可以向里面添加元素,如果存储满了就会自动扩容.扩容规则:新开辟的数组空间是上一个数组长度的1.5倍, 然后在向其中添加元素.

链表结构:
链表结构的特点:增删快(每个元素都记录了下一个元素的地制值,当我 们进行增删时,只需要把两个元素的地址值更换即可),查询慢(链表结构 不是连续的空间,每查找元素都会从头开始查找);

LinkedList集合:查询特点:根据索引查询元素,判断查询的索引是大于 还是小于集合长度的1/2;如果大于1/2,从后往前一个一个的查询;如果 小于1/2,从前往后一个一个的查询.

链表是由一系列节点(链表中每个元素称为节点)组成的,节点可以在运 行时动态生成;每个节点包括两个部分:一个是存储数据元素的数据域, 另一个是存储下一个节点地址的指针域.

Iterator和ListIterator的区别和联系:
一: ListIterator有add()方法,可以向集合中添加元素,而Iterator 不可以.
二: ListIterator有hasPrevious()和previous()方法,可以逆向遍历 集合,而Iterator就不可以逆向遍历集合.
三: ListIterator可以定位当前索引位置,nextIndex()和 previousIndex()方法可以实现,而Iterator没有此功能.
四: 都可以实现删除对象,但是ListIterator可以实现对对象的修改,通 过set()方法来实现;而Iterator只能遍历,不能修改对象.

HashMap和Hashtable的区别:
相同点:
都是双列集合; 键都是唯一的.
不同点:

  1. 出现的版本不同:
    HashMap是在1.2版本出现的;
    而Hashtable是在1.0版本就出现了.
  2. 线程同步的区别:
    HashMap是不同步的,效率高但是不安全;
    Hashtable是同步的,效率低但安全.
  3. 存储数据不同:
    HashMap可以存储null键和null值
    Hashtable不可以存储null键和null值.

自定义异常需要添加一个带有异常信息的构造方法,通过查看原码发现所有的异常类都会有一个带有异常信息的构造方法,通过super关键字调用父类的异常信息的构造方法,让父类来处理这个异常信息.

什么是进程和线程?
进程是应用程序在内存中的执行区域.
线程是进程的一个执行区域,负责程序的运行,进程中包含多个线程.

同步代码块和lock锁的区别:
同步代码块:就是一个代码块,说白了就是一对大括号,而且需要同一对 象作为锁对象;在使用同步代码块的时候还要考虑是否使用的是同一个 锁对象.
Lock锁是一个接口,我们使用它的实现类(ReentrantLock)对象作为锁 对象,这样更加面向对象一些,而且不需要考虑是否使用同一个锁对象.

如果wait();方法不传递参数就是一直等待,直到唤醒;而且在等待后它可以释放锁对象.

Lambda表达式中,如果{}中只有一行代码,无论是否有返回值,则可以省略大 括号和return和分号;注意:如果要省略就必须{}和return和分号一起省略

线程池的作用:可以达到资源利用的效果,而且资源利用率大大提高.
代码格式:ExecutorService es = Executors.newFixedThreadPool(2);
es.submit(new RunnableImpl());
//es.shutdown();可以销毁线程池,但不建议使用,因为创建线程 池就是为了使用的,而不是让它销毁.

File类:
static String pathSeparator; 与系统有关的路径分隔符,为了方便使 用,用字符串表示.
static String separator;与系统有关的名称分隔符.
String getAbsolutePath();获取绝对路径.
long length();获取文件的大小.
public boolean createNewFile();当且仅当具有该名称的文件不存在的 时候才会创建一个空的文件.创建文件的路径和名称在构造方法中给出.
public boolean delete();删除文件或文件夹,如果是文件夹则必须为空. 它是直接在硬盘中删除,因此删除需谨慎.
public boolean mkdirs();创建单级文件夹或多级文件夹目录,创建文件 夹的路径和名称在构造方法中给出(作为构造方法的参数传递).

Properties类:
public Object setProperty(String key, String value):保存一对 属性(默认都是String类型)。
public String getProperty(String key) :使用此属性列表中指定的 键搜索属性值。
public Set stringPropertyNames() :所有键的名称的集合。
public void load(InputStream inStream) : 从字节输入流中读取键 值对(此方法常用于加载配置文件)。

编码表:
ASCII码表:美国的一种码表(美国信息交换标准代码)。包含了英文大 小写字母、数字、特殊符号等等…
ISO-8859-1码表:欧洲各个国家的使用的码表
gb2312码表:最早的中文码表
gbk码表:包含中文的码表,目前使用最多的中文码表
gb18030码表:最新的中文码表
Unicode码表:万国码。包含了所有的码表

OutputStreamWriter(OutputStream out,String charSetName):是字符流通向字节流的桥梁.以指定的编码格式进行写出数据.
InputStreamReader(InputStream is,String charsetName):是字节流通向 字符流的桥梁!根据指定的编码格式进行读取文件.

序列化就是将对象写入到文件中,而反序列化就是将文件中的对象信息读取出来.
对象输出流:
构造方法:
ObjectOutputStream(OutputStream out);创建一个对象输出流 对象
成员方法:
writeObject(Object obj); 将传入的对象进行写出
close(); 释放资源
对象输入流:
构造方法:
ObjectInputStream(InputStream is); 创建一个对象输入流对象
成员方法:
Object readObject(); 读取文件中的对象
close(); 释放资源
使用序列化操作可能会出现的异常:
A: NotSerializableException
出现的原因:被序列化的类没有实现 Serializable 接口
解决的方案:让该类实现 Serializable 接口
B: InvalidClassException
出现的原因:序列化的id不匹配
解决的方案:生成一个固定的序列化id号即可

特殊的本机IP地址:
127.0.0.1 localhost

Socket类:该类实现客户端套接字,套接字指的是两台设备之间通讯的端点。

ServerSocket类:这个类实现了服务器套接字,该对象等待通过网络的请求。

“语法糖”是指使用更加方便,但是原理不变的代码语法。例如在遍历集合时使用的for-each语法,其实底层的实现原理仍然是迭代器,这便是“语法糖”。
有些场景的代码执行后,结果不一定会被使用,从而造成性能浪费。而Lambda 表达式是延迟执行的,这正好可以作为解决方案,提升性能。

常用的函数式接口:
Supplier 包含了一个抽象的get()方法,用于获取数据(生产数据)
Consumer 包含了一个抽象的accept()方法,用于使用数据(消费数据); 还有默认方法andThen(),用于组合操作.例如:
one.andThen(two).accept(info);
Predicate 包含了一个抽象的test()方法,用于数据的判断.既然是条 件判断就包含与 或 非三种默认方法,and()并且关系,or()或者关系,
negate()取反关系.例如:
boolean veryLong = predicate.negate().test(“HelloWorld”);注意此 时是后调用test()方法的,和and,or一样.
Function: java.util.function.Function 接口用来根据一个类 型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件
Function 接口中最主要的抽象方法为: R apply(T t) ,根据类型T 的参数获取类型R的结果。也有默认方法andThen(),和Consumer一样.

Stream流:
java.util.stream.Stream 是Java 8新加入的最常用的流接口。(这 并不是一个函数式接口。)
常用的获取流的方式:
所有的 Collection 集合都可以通过 stream() 默认方法获取流 (双 列集合Map只能分别获取键(keySet())和值values()或者调用 entrySet().stream()获得Stream流的set集合);
Stream 接口的静态方法 of 可以获取数组对应的流.
常用方法:
逐一处理:forEach 该方法接收一个 Consumer 接口函数,会将每 一个流元素交给该函数进行处理。
过滤:filter 该接口接收一个 Predicate 函数式接口参数(可以 是一个Lambda或方法引用)作为筛选条件。例如:
original.filter(s -> s.startsWith(" 张"));
映射:map 该接口需要一个 Function 函数式接口参数,可以将当 前流中的T类型数据转换为另一种R类型的流。例如:
original.map(str->Integer.parseInt(str));
统计次数:count 该方法返回一个long值代表元素个数(不再像旧 集合那样是int值)。
取用前几个: limit 参数是一个long型,如果集合当前长度大于 参数则进行截取;否则不进行操作。
跳过前几个: skip 如果流的当前长度大于n,则跳过前n个;否则 将会得到一个长度为0的空流。
组合:concat 如果有两个流,希望合并成为一个流,那么可以使用 Stream 接口的静态方法 concat.

方法引用
双冒号 :: 为引用运算符,而它所在的表达式被称为方法引用。如果 Lambda要表达的函数方案已经存在于某个方法的实现中,那么则可以通 过双冒号来引用该方法作为Lambda的替代者。例如:
Lambda表达式写法: s -> System.out.println(s);
方法引用写法: System.out::println;
通过对象名引用成员方法,通过类名称引用静态方法,通过super引用成 员方法,通过this引用成员方法,类的构造器引用(由于构造器的名称与 类名完全一样,并不固定。所以构造器引用使用 类名称::new 的格式 表示。),数组的构造器引用(例:方法引用: int[]::new).

线程在执行过程中,可以处于下面几种状态:
就绪(Runnable):线程准备运行,不一定立马就能开始执行。
运行中(Running):进程正在执行线程的代码。
等待中(Waiting):线程处于阻塞的状态,等待外部的处理结束。
睡眠中(Sleeping):线程被强制睡眠。
I/O阻塞(Blocked on I/O):等待I/O操作完成。
同步阻塞(Blocked on Synchronization):等待获取锁。
死亡(Dead):线程完成了执行.

反射
Java反射机制是在运行状态中,对于任意一个类,能知道所有的属性和方法;对于任意一个对象,都能调用它的任意属性和方法;这种动态的获 取信息以及动态调用方法的功能称为java的反射机制.总结:就是把 java类中的成分映射成一个一个的对象去使用.
通过反射创建新的类实例有两种,即:
1.Class.newInstance();只能调用公共无参的构造函数,即默认的构造 函数,Class类中特有的.
2.Constructor.newInstance();可以根据传递的参数调用任意的构造函 数,特定情况下可以调用私有的构造函数.
(Constructor getDeclaredConstructor(Class…c)?
(去除私有权限 setAccessible(true)?

你可能感兴趣的:(JavaSE)