JavaSE基础
本文为作者在学习和笔试题中遇到的小知识点总结,做以总结和备用。
jdk的安装和配置环境变量
(1)以win10为例,右键此电脑,选择属性,进去系统设置,选择高级系统设置,进入环境变量的配置。
(2)在系统变量中点击新建,变量名为JAVA_HOME,变量值为jdk的安装路径,单击保存。
(3)在系统变量中找到Path,双击打开,单击新建,输入jdk安装路径in,单击确定,保存后退出。
(4)在命令提示符窗口中输入java,javac,若出现如下信息则配置成功。
Java跨平台原理
Java是解释型语言,先将源代码编译成字节码,然后依赖各种不同平台上的虚拟机来解释执行字节码,从而实现了一次编写,到处运行。
Java:Java源程序(编译) --> .class字节码文件(在虚拟机上解释) --> 机器码 --> CPU
C/C++: C/C++源程序(编译) --> 机器码 --> CPU
一个以.java为后缀的源文件只能有一个与文件名相同的public类,可以包含其他类。
包
包(package)由一组类(class)和接口(interface)组成。
import导包
导包只可以导到当前层,不可以再导入包里面的类。
编码和编码格式
编码:编码就是一个编号(数字)到字符的一种映射关系,就仅仅是一种一对一的映射而已,可以理解成一个很大的对应表格,如Unicode,ASCII
编码格式:编码格式是用来序列化或存储编码中提到的那个“编号(数字)”的一种“格式”,包括gbk和utf-8。
gbk:是指中国的中文字符,其中它包含了简体中文与繁体中文字符
UTF-8:它是一种全国家通过的一种编码
实现GBK编码(src)字节流到UTF-8编码(str)字节流的转换:
String src = "";
String str = new String(src,"GBK").getBytes("UTF-8")
先通过GBK编码还原字符串,在该字符串正确的基础上得到“UTF-8”所对应的字节串。
Java的默认字符集是unicode。占2个字节(byte)。一个字节等于8比特位(bit)。所以每个Unicode码占用16个比特位。
ASCII和ANSI
(1)标准ASCII只使用7个bit,扩展的ASCII使用8个bit。
(2)ANSI通常使用 0x00~0x7f 范围的1 个字节来表示 1 个英文字符。超出此范围的使用0x80~0xFFFF来编码,即扩展的ASCII编码。不同 ANSI 编码之间互不兼容。在简体中文Windows操作系统中,ANSI 编码代表 GBK 编码;在繁体中文Windows操作系统中,ANSI编码代表Big5;在日文Windows操作系统中,ANSI 编码代表 Shift_JIS 编码。
(3)ANSI通常使用0x00~0x7f范围的1个字节来表示1个英文字符,即扩展的ASCII码
(4)ASCII码包含一些特殊空字符,不全是可打印字符。
常见的ASCII码值为:
空格的ASCII码值为32;
数字0到9的ASCII码值分别为48到57;
大写字母“A”到“Z”的ASCII码值分别为65到90;
小写字母“a”到“z”的ASCII码值分别为97到到122。
关键字和保留字
链接为Java官方定义的关键字列表,http://download.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html
关键字对java的编译器有特殊的意义,他们用来表示一种数据类型,或者表示程序的结构等。java中所有的关键字都是小写的。native本地是关键字
保留字是为java预留的关键字,他们虽然现在没有作为关键字,但在以后的升级版本中有可能作为关键字。const和goto是java的保留字。
Java中true ,false , null在java中不是关键字,也不是保留字,它们只是显式常量值,但是你在程序中不能使用它们作为标识符。
左移和右移
<<左移,相当于乘以2的几次方。
>>右移,相当于除以2的几次方。
>>表示带符号右移;>>>无符号右移,左边空出的位以0填充。没有<<<运算符
x=5>>2; == 5/2*2 x=1
y=x>>>2; y=0
&&,&和||, |
&&短路与,&逻辑与
String str = null; if (str != null && (str.length() > 0)) { System.out.println("短路与"); }
//执行以上代码,程序不会抛出异常
String str = null; if (str != null & (str.length() > 0)) { System.out.println("逻辑与"); }
//执行以上代码,程序会抛出空指针异常
原因是因为&&会造成短路,str != null 为false,后面的代码不会执行,所以不会抛出异常。&则不会发生短路,判断完 str != null 为false后,继续执行str.length(),由于str为null,则会抛出空指针异常。
||短路或,|逻辑或
短路或和逻辑或之间的关系同上,||中,当第一个值为true时,后面判断代码不会执行。|不管怎样都会执行。
位运算符
位运算符主要针对两个二进制数的位进行逻辑运算。参考博客: http://blog.csdn.net/u014082714/article/details/52052490
&(与)
两个操作数中位都为1,结果才为1,否则结果为0
int a = 129; int b = 128; System.out.println(a&b);
以上代码的运行结果是:128
“a”的值是129,转换成二进制就是10000001,而“b”的值是128,转换成二进制就是10000000。根据与运算符的运算规律,只有两个位都是1,结果才是1,可以知道结果就是10000000,即128。
|(或)
两个位只要有一个为1,那么结果就是1,否则就为0
int a = 129; int b = 128; System.out.println(a|b);
以上代码的运行结果是:129
“a”的值是129,转换成二进制就是10000001,而“b”的值是128,转换成二进制就是10000000。根据或运算符的运算规律,只要两个位数之间有一个1,结果才是1,可以知道结果就是10000001,即128。
~(非)
如果位为0,结果是1,如果位为1,结果是0
int a = 10; System.out.println(~a);
以上代码的运行结果是:7
“a”的值为10,转换成二进制是1000,按位取反后的值为0111,即7。
^(异或)
两个操作数的位中,相同则结果为0,不同则结果为1
int a = 12; int b = 5; System.out.println(a^b);
以上代码的运行结果是:13
a 的值是15,转换成二进制为1111,而b 的值是2,转换成二进制为0010,根据异或的运算规律,可以得出其结果为1101 即13。
格式化输出
在Java5中,推出了c语言中的printf()风格的格式化输出。使用java.io.PrintSteam中printf方法实现。
public PrintStream printf(String format, Object... args) 参数: format: 在格式字符串的语法中描述的格式字符串。 args:格式字符串中的格式说明符引用的参数。 形式: System.out.printf(format,args)
%s表示输出字符串;%d表示将整数格式化为10进制整数;%f表示以十进制格式化输出浮点数。%.2f表示的是小数点后两位。
String s = "abc"; int i = 10; float f = 3.1415926f; System.out.printf("s = %s;i = %d;f = %.2f", s,i,f);
以上代码的运行结果是:s = abc;i = 10;f = 3.14
Scanner类
java.util.Scanner,从控制台扫描数据
Scanner sc = new Scanner(System.in);
扫描String类型数据时,调用sc.next()和sc.nextLine()。
区别:
next()一定要读取到有效字符后才可以结束输入,对输入有效字符之前遇到的空格键、Tab键或Enter键等结束符,next()方法会自动将其去掉,只有在输入有效字符之后,next()方法才将其后输入的空格键、Tab键或Enter键等视为分隔符或结束符。
简单地说,next()查找并返回来自此扫描器的下一个完整标记。完整标记的前后是与分隔模式匹配的输入信息,所以next方法不能得到带空格的字符串。
nextLine()方法的结束符只是Enter键,即nextLine()方法返回的是Enter键之前的所有字符,它是可以得到带空格的字符串的。
next()
nextLine()
基本数据类型
类型 |
字节数 |
默认值 |
取值范围 |
字节型byte |
1 |
0 |
-27~27-1 |
字符型char |
2 |
‘u0000’ |
0~216-1 |
short |
2 |
0 |
-215~215-1 |
int |
4 |
0 |
-231~231-1 |
long |
8 |
0 |
-263~263-1 |
float |
4 |
0.0f |
-3.4*10-38~3.4*10-38 |
double |
8 |
0.0 |
-1.7*10-308~1.7*10-308 |
boolean |
1 |
false |
ture/false |
自动类型转换:
byte,short,char -> int -> long -> float -> double
float占4个字节比long占8个字节大,浮点数最大值比长整型的范围大。
Java中的byte,short,char进行计算时都会提升为int类型。若有一个操作数是long型,计算结果是long型;如果有一个操作数是float型,计算结果是float型;如果有一个操作数是double型,计算结果是double型。
short s = 1; s = s + 1;//编译器会报错,运行时先将s转为int类型,s+1结果为int类型。 s += 1;//不会出错,+=是Java规定的运算符,编译器会进行特殊处理。
例子:
byte b1 = 1, b2 = 2, b3, b6, b8;
final byte b4 = 4, b5 = 6, b7;
b3 = (b1+b2);//错误,byte自动转为int,所以正确写法为b3=(byte)(b1+b2);
b6 = b4+b5;//正确,被final修饰的变量不会自动改变类型;
b8 = (b1+b4);//错误,b1会自动提升,结果需要强转;
b7 = (b2+b5);//错误,同上。同时注意b7是final修饰,即只可赋值一次,便不可再改变。
包装类
基本数据类型 |
包装类 |
byte |
Byte |
boolean |
Boolean |
short |
Short |
char |
Character |
int |
Integer |
long |
Long |
float |
Float |
double |
Double |
基本数据类型和包装类之间的转换。
装箱:值类型转换为引用类型;
拆箱:引用类型转换为值类型。
Math类
java.lang.Math类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。
Math.ceil(-0.5); // -0.0求大于参数的最大整数。返回double类型 Math.floor(-0.5); // -1.0求小于参数的最小整数。返回double类型 Math.round(-4.6): // -5 对小数进行四舍五入后的结果。返回int类型
ceil:大于等于 x,并且与它最接近的整数。天花板数,向上取整。
floor:小于等于 x,且与 x 最接近的整数。地板数,向下取整。
Math.cos()为计算弧度的余弦值。若要计算cos(60°),必须先将60度转为弧度。
double hd = Math.toRadians(60); double c = Math.cos(hd); // c的值为0.500000
toRadians()函数讲角度转换为弧度, toDegrees()是将弧度转换为角度。
Math.PI 即π
Math.sqrt(a) 计算a的平方根
判断一个数开平方后是否为整数:Math.sqrt(i)%1 == 0
例子:输出1-100之间开方后是整数的数:
for (int i = 1; i <= 100; i++) { if (Math.sqrt(i)%1 == 0) { System.out.println(i); } }
Object类
Object类中的方法:
clone() |
创建并返回此对象的一个副本。 |
equals() |
指示其他某个对象是否与此对象“相等”。 |
finalize() |
对象的垃圾回收器调用此方法 |
getClass() |
返回此Object的运行类 |
hashCode() |
返回对象的哈希码值 |
notify() |
唤醒在此对象监视器上等待的单个线程 |
notifyall() |
唤醒在此对象监视器上等待的所有线程 |
toString() |
返回该对象的字符串表示 |
wait() |
在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。 |
wait(long timeout) |
在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。 |
wait(long timeout,intnanos) |
在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导致当前线程等待。 |
clone()
Java在处理基本数据类型时,采用按值传递(传递的是输入参数的复制)的方式执行,除此之外其他类型都是按引用传递(传递的是对象的一个引用)的方式执行。对象除了在函数调用时是引用传递,在使用“=”赋值时也采用引用传递。
遇到从某个已有的对象A创建出另外一个与A具有相同状态的对象B,并且对B的修改不会影响到A的状态。Java中简单的赋值操作无法达到这个目的。Object类中提供了一个clone()方法。这个方法时返回一个Object对象的复制,这个复制函数返回的是一个新的对象而不是一个引用。
BigInteger类
java.math.BigInteger
BigInteger 任意大的整数,原则上是,只要你的计算机的内存足够大,可以有无限位的
BigInteger 任意大的实数,可以处理小数精度问题。
将int型的数赋值给BigInteger,BigInteger.valueOf(k);
基本的方法:
BigInteger val
valueOf(long val) |
赋初值 |
add(val) |
a.add(b); |
subtract(val) |
- |
multiply(val) |
* |
divide(val) |
/ |
remainder(val) |
this % val |
pow(int val) |
a.pow(b)=a^b |
gcd,abs |
公约数,绝对值 |
negate() |
取负数 |
signum() |
符号函数 |
mod(val) |
a.mod(b)=a%b |
||
shiftLeft(int n) |
左移,this << n ,this*2^n; |
||
shiftRight(int n) |
右移,this >> n,this/2^n |
||
compareTo(val) |
根据该数值是小于、等于、或大于 val 返回 -1、0 或 1 |
||
equals(Object x) |
判断两数是否相等,也可以用compareTo来代替 |
||
min,max |
取两个数的较小、大者 |
||
isProbablePrime(int certainty) |
如果该 BigInteger 可能是素数,则返回 true ;如果它很明确是一个合数,则返回 false |
String中的方法
1、public String substring(int beginIndex,int endIndex)
返回一个新字符串,它是此字符串的一个子字符串。该子字符串从指定的 beginIndex 处开始,直到索引 endIndex - 1 处的字符,不包含后一位。
"hamburger".substring(4, 8) returns "urge"
"smiles".substring(1, 5) returns "mile"
2、public String substring(int beginIndex)
返回一个新的字符串,它是此字符串的一个子字符串。该子字符串从指定索引处的字符开始,直到此字符串末尾。
"unhappy".substring(2) returns "happy"
"Harbison".substring(3) returns "bison"
"emptiness".substring(9) returns "" (an empty string)
3、public boolean contains(CharSequence s)
当且仅当此字符串包含指定的 char 值序列时,返回 true。底层是调用indexof方法
public boolean contains(CharSequence s) { return indexOf(s.toString()) > -1; }
4、public int indexOf(String str)
返回指定子字符串在此字符串中第一次出现处的索引。若不存在则返回-1;
String、StringBuffer、StringBuilder
String:字符串常量,字符串长度不可变。Java中String是immutable(不可变)的。
StringBuffer:字符串变量(Synchronized,即线程安全)。如果要频繁对字符串内容进行修改,出于效率考虑最好使用StringBuffer,如果想转成String类型,可以调用StringBuffer的toString()方法。
Java.lang.StringBuffer线程安全的可变字符序列。在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。可将字符串缓冲区安全地用于多个线程。StringBuffer 上的主要操作是 append 和 insert 方法
StringBuilder:字符串变量(非线程安全)。在内部,StringBuilder对象被当作是一个包含字符序列的变长数组。
java.lang.StringBuilder是一个可变的字符序列,是JDK5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候
(1)Java中的字符串存储在字符常量区,不会改变,发生改变的是会新创建一个对象。
(2)StringBuffer是线程安全的
(3)StringBuilder线程不安全
(4)StringBuilder和StringBuffer底层都是以字符数组存放的,可以修改内容
效率:StringString(出生于JDK1.0时代)不可变字符序<StringBuffer(出生于JDK1.0时代)线程安全的可变字符序列<StringBuilder(出生于JDK1.5时代)非线程安全的可变字符序列。
正则表达式
java.util.regex包中有两个类,Pattern和Matcher类。Pattern是用来表达和陈述所要搜索模式的对象,Matcher类是真正影响搜索的对象。
d数字 D非数字
Pattern p = Patter.compile(String regex);//将给定的正则表达式编译到模式中。 Matcher m = Matcher(String str);//创建匹配给定输入与此模式的匹配器。
Matcher类
matches()
返回boolean,尝试将整个区域与模式匹配。
replaceAll(String replacement)
返回String,替换模式与给定替换字符串相匹配的输入序列的每个子序列。
Pattern类
compile(String regex)
返回Pattern,将给定的正则表达式编译到模式中。
matcher(CharSequence input)
返回Matcher,创建匹配给定输入与此模式的匹配器。
split(CharSequence input)
返回String[],围绕此模式的匹配拆分给定输入序列。
String中有3个方法支持正则操作
matches(String regex)
返回boolean,字符串匹配的方法
replaceAll(String regex,String replacement)
返回String,字符串替换的方法
split(String regex)
返回String[],字符串拆分的方法。
数组复制的方法
1、for循环逐逐一复制;
2、System.arraycopy;
3、Array.copyof;
4、使用clone方法。
效率:System.arraycopy > clone > Arrays.copyOf > for循环
形参
形式参数可被视为local variable。形参和局部变量一样都不能离开方法。只有在方法中使用,不会再方法外可见。
形式参数只能用final修饰,其他任何修饰符都会引起编译器错误。一般情况下,一个方法的形参不用final修饰。只有在特殊情况下,那就是方法内部类。
形式参数为方法调用时,真正传递的是实参。
方法的参数列表指定要传递给方法什么样的信息,采用的都是对象的形式。因此,在参数列表中必须指定每个所传递对象的类型及名字。想JAVA中任何传递对象的场合一样,这里传递的实际上也是引用,并且引用的类型必须正确。
File类
文件分为文本文件和二进制文件,计算机只认识二进制,所以实际上都是二进制的不同解释方式。文本文件是以不同编码格式显示的字符,例如Ascii、Unicode等,window中文本文件的后缀名有".txt",".log",各种编程语言的源码文件等;二进制文件就是用文本文档打开是看不懂乱码,只要能用文本打开的文件都可以算是文本文件,只是显示的结果不是你想要的,二进制文件只有用特殊的应用才能读懂的文件,例如".png",".bmp"等,计算机中大部分的文件还是二进制文件。
File类是对文件整体或者文件属性操作的类,例如创建文件、删除文件、查看文件是否存在等功能,不能操作文件内容;文件内容是用IO流操作的。
当输入过程中意外到达文件或流的末尾时,抛出EOFException异常,正常情况下读取到文件末尾时,返回一个特殊值表示文件读取完成,例如read()返回-1表示文件读取完成。
泛型
1、创建泛型对象的时候,一定要指出类型变量T的具体类型。争取让编译器检查出错误,而不是留给JVM运行的时候抛出类不匹配的异常。
2、JVM如何理解泛型概念——类型擦除。事实上,JVM并不知道泛型,所有的泛型在编译阶段就已经被处理成了普通类和方法。处理方法很简单,我们叫做类型变量T的擦除(erased) 。
总结:泛型代码与JVM
①虚拟机中没有泛型,只有普通类和方法。
②在编译阶段,所有泛型类的类型参数都会被Object或者它们的限定边界来替换。(类型擦除)
③在继承泛型类型的时候,桥方法的合成是为了避免类型变量擦除所带来的多态灾难。无论我们如何定义一个泛型类型,相应的都会有一个原始类型被自动提供。原始类型的名字就是擦除类型参数的泛型类型的名字。
泛型仅仅是java的语法糖,它不会影响java虚拟机生成的汇编代码,在编译阶段,虚拟机就会把泛型的类型擦除,还原成没有泛型的代码,顶多编译速度稍微慢一些,执行速度是完全没有什么区别的。
字节流和字符流
(1)字节流:
InputStream
-- FileInputStream (基本文件流)
-- BufferedInputStream
-- DataInputStream
-- ObjectInputStream
(2)字符流
Reader
-- InputStreamReader (byte->char 桥梁)
-- BufferedReader (常用)
Writer
-- OutputStreamWriter (char->byte 桥梁)
-- BufferedWriter
-- PrintWriter (常用)
stream结尾都是字节流,reader和writer结尾都是字符流两者的区别就是读写的时候一个是按字节读写,一个是按字符。实际使用通常差不多。在读写文件需要对内容按行处理,比如比较特定字符,处理某一行数据的时候一般会选择字符流。只是读写文件,和文件内容无关的,一般选择字节流。
字符流=字节流+编码集
null
null是代表不确定的对象,null是一个关键字。可以将null赋值给引用类型变量,但不可以将null赋值给基本类型变量。比如int a = null ×,object o = null是正确的。
null可以被强制类型转换成任意类型(不是任意类型对象)。可以通过他来执行静态方法。(TestClass)null == TestClass
反射
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用他的任意一个方法和属性;是一种动态获取信息和动态调用对象的方法。
获取Class类:
①Class.forName(“类的路径”);
②类名.Class
③实例.getClass()
反射机制的作用
①通过一个对象获得完整的包名和类名;对象.getClass().getName()
②实例化Class对象;Class.forName()
③获得一个对象的父类和实现的接口;clazz.getSuperClass(),clazz.getInterfaces()