文章目录
1、jdk配置
JAVA_HOME
D:\Soft\Java\jdk1.5.0
PATH
;%JAVA_HOME%\bin;
CLASSPATH
.;%JAVA_HOME%/lib/dt.jar;%JAVA_HOME%/lib/tools.jar;
多个jdk配置在同一台电脑上时,切换后java与javac版本不一致的解决办法:
删除C:\Windows\System32
目录下的java.exe
,删除即可。有时也需要删除javaw.exe
和javax.exe
若java -version
和javac -version
版本不一致
将%JAVA_HOME%\bin
加在PATH变量的头,执行java -version
和javac -version
,版本已然一致
2、访问权限
权限 | 类内 | 同包 | 不同包子类 | 不同包非子类 |
---|---|---|---|---|
public | √ | √ | √ | √ |
protect | √ | √ | √ | × |
default | √ | √ | × | × |
private | √ | × | × | × |
3、类型
3.1、基本类型
类型 | 大小 | 范围 | 默认值 |
---|---|---|---|
byte | 8 | -128 - 127 | 0 |
short | 16 | -32768 - 32768 | 0 |
int | 32 | -2147483648-2147483648 | 0 |
long | 64 | -9233372036854477808-9233372036854477808 | 0 |
float | 32 | -3.40292347E+38-3.40292347E+38 | 0.0f |
double | 64 | -1.79769313486231570E+308-1.79769313486231570E+308 | 0.0d |
char | 16 | \u0000 - u\ffff | \u0000 |
boolean | 16 | true/false | false |
3.2、包装类
基本数据类型 | 默认值 | 包装类 | 默认值 | 描述 |
---|---|---|---|---|
byte | 0 | Byte | null | |
short | 0 | Short | null | |
char | 空格 | Character | null | |
int | 0 | Integer | null | |
float | 0.0 | Float | null | |
long | 0 | Long | null | |
double | 0.0 | Double | null | |
boolean | false | Boolean | null | |
- | - | BigInteger | null | 支持任意精度的整数 |
- | - | BigDecimal | null | 支持任意精度带小数点的运算 |
3.3、基本类型和包装类型的异同
-
在Java中,一切皆对象,但八大基本类型却不是对象。
-
声明方式的不同,基本类型无需通过new关键字来创建,而封装类型需new关键字。
-
存储方式及位置的不同,基本类型是直接存储变量的值保存在堆栈中能高效的存取,封装类型需要通过引用指向实例,具体的实例保存在堆中。
-
初始值的不同,封装类型的初始值为null,基本类型的的初始值视具体的类型而定
-
使用方式的不同,比如与集合类合作使用时只能使用包装类型。
-
什么时候该用包装类,什么时候用基本类型,看基本的业务来定:这个字段允不允许null值,如果允许null值,则必然要用封装类,否则值类型就可以了,用到比如泛型和反射调用函数.,就需要用包装类!在阿里巴巴的规范里所有的POJO类必须使用包装类型,而在本地变量推荐使用基本类型。
3.4、自动拆装箱的比较
- 包装类的比较
Integer a = 1;
Integer b = 1;
Integer c = 144;
Integer d = 144;
Integer a1 = new Integer(1);
Integer b1 = new Integer(1);
System.out.println(a == b); //true
System.out.println(a.equals(b)); //true
System.out.println(a1 == b1); //false
System.out.println(a1.equals(b1)); //true
System.out.println(c == d); //false
System.out.println(c.equals(d)); //true
注意:在自动装箱时对于值从–128到127之间的值,它们被装箱为Integer对象后,会存在内存中被重用,始终只存在一个对象 。而如果超过了从–128到127之间的值,被装箱后的Integer对象并不会被重用,即相当于每次装箱时都新建一个Integer对象。(享元模式的设计模式)
类型 | 自动装箱池的范围 |
---|---|
Integer | -128 - 127 |
Byte、Short、Long | -128 - 127 |
Character | 0 - 127 |
Float、Double | 没有自动装箱池 |
问题:在进行==比较的时候,在自动装箱池范围内的数据的引用是相同的,范围外的是不同的
-
在使用自动拆箱时,一定要确保包装类的引用不为空
-
自动拆装箱的比较
Integer aa=400;
int bb=400;
System.out.println(aa==bb);//true
解析:==运算是判断两个对象的地址是否相等或者判断两个基础数据类型的值是否相等。aa进行自动拆箱,所以比较的是两个基本数据类型,所以相等。如果+、-、*、/呢?
1 Integer integer100 = 100;
2 int int100 = 100;
3 Long long200 = 200l;
4 System.out.println(integer100 + int100);//200
5 System.out.println(long200 == (integer100 + int100));//true
6 System.out.println(long200.equals(integer100 + int100));//false
第4行中,integer100+int100就会得到一个类型为int且value为200的基础数据类型b,再将b进行装箱得到o,执行这个对象的toString()方法,并输出”200”;
第5行中,integer100+int100就会得到一个类型为int且value为200的基础数据类型b1,== 运算将long200进行拆箱得到b2,显然b1==b2,输出true;
第6行中,integer100+int100就会得到一个类型为int且value为200的基础数据类型b,Long的equals方法将b进行装箱,但装箱所得到的是类型为Integer的对象o,因为o与long200为不同的类型的对象,所以输出false;
4、集合
4.1、deque
是双端开口的数据结构,即两头可进可出。
4.2、stack
是一种先进后出(FILO)的数据结构,它只有一个接口。SGI STL便以deque作为缺省情况下的stack底部结构,封闭其头端开口。stack没有迭代器,所以除了顶部元素,无法存取其他元素,即不能遍历stack
4.3、queue
是一种先进先出(FIFO)的数据结构,它有两个出口。queue也是以deque作为底部结构,封闭其底端的出口和前端的入口。只有顶端的元素能被外部使用,所以queue也没有迭代器,不能提供遍历功能。
ArrayBlockingQueue 一个由数组支持的有界队列。这是一个典型的有界缓存区,固定大小的数组在其中保持生产者插入的元素和使用这提取的元素。一旦创建了这样的缓存区,就不能在增加其容量。试图向已满队列中放入元素会导致操作受阻塞,试图从空队列中提取元素会导致类似的阻塞。实现线程安全,作为生产者消费者的首选。
LinkedBlockingQueue 线程安全的阻塞队列。可以指定容量,也可以不指定话,默认最大是Integer.MAX_VALUE,其中主要用到put和take方法,put方法在队列满的时候会阻塞直到有队列成员被消费,take方法在队列空的时候会阻塞,直到有队列成员被放进来。
ConcurrentLinkedQueue 是Queue的一个安全实现,按FIFO原则排序,采用CAS操作,来保证元素的一致性。
5、时间
5.1、Date
new Date();当前时间
date1.after(date2) date1在date2之后返回true
before()与after相反
date1.compareTo(date2) date1在date2之后返回1,相等0,之前-1
getTime() 得到毫秒数,1970.1.1 00:00:00
setTime(long time) 设置时间 long
5.2、DateFormat
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
5.3、Calendar
Calendar calendar= Calendar.getInstance();
calendar.setTime(Date);
6、颜色
6.1、保存颜色
颜色 | 范围 |
---|---|
红 | 0~255 |
黄 | 0~255 |
蓝 | 0~255 |
透明度(alpha) | 0~255(不透明) |
可用int类型保存
int共四个字节
00000000(alpha)00000000(red)00000000(yellow)00000000(blue)
int red = 255;
int yellow = 255;
int blue = 255;
int alpha = 255;
int color = alpha<<24 | red<<16 | yellow<<8 | blue
7、比较器
7.1、内部比较器
需比较的类实现接口 Comparable,使该类对外提供一个默认比较的实现
public class test implements Comparable<test>{
//负整数、零、整数分别代表小于、等于、大于指定对象
@Override
public int compareTo(test t){}
}
7.2、外部比较器
需比较的类不做任何实现,该类通过工具类Collections调用sort方法传入一个实现了接口 Comparator的类和一个List
Collections.sort(list, new MyComparator());//传入list和比较器排序
public class MyComparator implements Comparator<Worker> {
/*
* 根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数
*/
@Override
public int compare(Worker o1, Worker o2) {}
}
总结:
TreeSet仅能根据创建时实现的comparable接口(内部比较器)进行排序,且HashSet不支持内部比较器,工具类Collections.sort()方法仅能对List排序。
在一个类没有提供比较器时或提供的比较器不适用时,就需要使用外部比较器,List(例如:拿到一个jar包但它的类没比较器,总不能反编译去改代码)
8、编码及编码格式
8.1、概念
编码
一个编号(数字)到字符的一种映射关系,仅仅是一对一的映射关系,可以理解成很大的对应表格。Unicode是一种编码
编码格式
用来序列化和存储“编号(数字)”的一种“格式”
GBK
和UTF-8
区别
作用:属于两种不同的编码格式,但都是用来序列化和存储Unicode编码的数据的
unicode编码范围:
utf-8
考虑了很多种不同国家的字符,涵盖整个unicode码表,所以其存储一个字符的编码的时候,使用的字节长度也从1字节到4字节不等;
GBK
只考虑中文在unicode中的一小部分的字符的编码,所以它算好了只要2个字节就能涵盖到绝大多数常用中文(2个字节能表示6w多种字符),所以它存储一个字符的时候,所用的字节长度是固定的。
内码
程序内部使用的字符编码,特别是某些语言实现其char或String类型在内存中使用的内部编码
外码
程序与外部交互时外部使用的字符编码,“外部”是相对与“内部”来说的
Java语言规范规定:
Java的char类型是UTF-16的code unit,也就是一定是16位(2字节):
char, whose values are 16-bit unsigned integers representing UTF-16 code units (§3.1)
.
字符串是UTF-16 code unit的序列:
The Java programming language represents text in sequences of 16-bit code units, using the UTF-16 encoding.
这样,Java规定了字符的内码要用UTF-16编码
String.getBytes()是一个用于将String的内码转换为指定的外码的方法。
无参数版使用平台的默认编码作为外码,有参数版使用参数指定的编码作为外码;
将String的内容用外码编码好,结果放在一个新byte[]返回。
谈“占几个字节”,就要先把编码说清楚
同一个字符在不同的编码下可能占不同的字节。
举“字”字为例,“字”在GBK编码下占2字节,在UTF-16编码下也占2字节,在UTF-8编码下占3字节,在UTF-32编码下占4字节。
不同的字符在同一个编码下也可能占不同的字节。
“字”在UTF-8编码下占3字节,而“A”在UTF-8编码下占1字节。(因为UTF-8是变长编码)。Java中的char本质上是UTF-16编码。而UTF-16实际上也是一个变长编码(2字节或4字节)。
如果一个抽象的字符在UTF-16编码下占4字节,显然它是不能放到char中的。换言之,char中只能放UTF-16编码下只占2字节的那些字符。而getBytes实际是做编码转换,你应该显式传入一个参数来指定编码,否则它会使用缺省编码来转换。你可以在启动JVM时设置一个缺省编码,否则,会使用所在操作系统环境下的缺省编码。
8.2、String类型:
java的string使用的编码是unicode。
当string存在于内存中时是“只有编码而没有编码格式的”
(在程序运行中用string类型的引用对它进行操作、也就是string没有被存在文件中且也没有在网络中传输(序列化)时)
所以java程序中的任何String对象,说它是gbk还是utf-8都是错的,gbk和utf-8是编码格式而不是编码,String在内存中不需要“编码格式”
(记住编码格式是在存文件或序列化的时候使用的)
它只是一个unicode的字符串而已,所以java里面String是不带编码格式的。
8.3、情景
一、如何把一个被错误地当作是gbk格式存储的utf-8格式的文件里面读出来的一段乱码字符串还原回去(也就是说本来二进制数据是utf-8的,你用gbk来解码它,得到的字符串是乱码,现在想要还原回去)
public static String recover(String str) throws Throwable {
return new String(str.getBytes("GBK"), "UTF-8");
}
二、如何把一个gbk文件转化为utf-8文件
那就用InputStream以gbk格式将文件读到内存里(表示为String),再将这个String以UTF-8编码写入目标文件里
9、Eclipse快捷键
快捷键 | 功能 |
---|---|
ALT+SHIFT+A | 竖排选择功能 |
ALT+SHIFT+R | 变量重命名 |
CTRL+SHIFT+F | 格式化代码 |
10、注解
10.1、注解用处
- 生成文档。这是最常见的,也是java 最早提供的注解。常用的有
@param
@return
等 - 跟踪代码依赖性,实现替代配置文件功能。比如
Dagger 2
依赖注入,未来java开发,将大量注解配置,具有很大用处; - 在编译时进行格式检查。如
@override
放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出。
10.2、注解原理
注解本质是一个继承了Annotation
的特殊接口,其具体实现类是Java运行时生成的动态代理类。而我们通过反射获取注解时,返回的是Java运行时生成的动态代理对象$Proxy1。通过代理对象调用自定义注解(接口)的方法,会最终调用AnnotationInvocationHandler
的invoke
方法。该方法会从memberValues
这个Map中索引出对应的值。而memberValues
的来源是Java常量池。
10.3、元注解
java.lang.annotation提供了四种元注解,专门注解其他的注解(在自定义注解的时候,需要使用到元注解)
@Documented –注解是否将包含在JavaDoc中
@Retention –什么时候使用该注解
@Target –注解用于什么地方
@Inherited – 是否允许子类继承该注解
-
@Documented
一个简单的Annotations标记注解,表示是否将注解信息添加在java文档中。 -
@Retention
定义该注解的生命周期
RetentionPolicy.SOURCE
: 在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。@Override
,@SuppressWarnings
都属于这类注解。RetentionPolicy.CLASS
: 在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式RetentionPolicy.RUNTIME
: 始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。
Target
表示该注解用于什么地方。默认值为任何元素,表示该注解用于什么地方。可用的ElementType参数包括
ElementType.CONSTRUCTOR
:用于描述构造器ElementType.FIELD
:成员变量、对象、属性(包括enum实例)ElementType.LOCAL_VARIABLE
:用于描述局部变量ElementType.METHOD
:用于描述方法ElementType.PACKAGE
:用于描述包ElementType.PARAMETER
:用于描述参数ElementType.TYPE
:用于描述类、接口(包括注解类型) 或enum声明
@Inherited
定义该注释和子类的关系
@Inherited
元注解是一个标记注解,@Inherited
阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited
修饰的annotation
类型被用于一个class
,则这个annotation
将被用于该class
的子类。
10.4、常见标准的Annotation
Override
java.lang.Override
是一个标记类型注解,它被用作标注方法。它说明了被标注的方法重载了父类的方法,起到了断言的作用。如果我们使用了这种注解在一个没有覆盖父类方法的方法时,java编译器将以一个编译错误来警示。
Deprecated
Deprecated
也是一种标记类型注解。当一个类型或者类型成员使用@Deprecated
修饰的话,编译器将不鼓励使用这个被标注的程序元素。所以使用这种修饰具有一定的“延续性”:如果我们在代码中通过继承或者覆盖的方式使用了这个过时的类型或者成员,虽然继承或者覆盖后的类型或者成员并不是被声明为@Deprecated,但编译器仍然要报警。
SuppressWarnings
SuppressWarning
不是一个标记类型注解。它有一个类型为String[]
的成员,这个成员的值为被禁止的警告名。对于javac
编译器来讲,被-Xlint
选项有效的警告名也同样对@SuppressWarings
有效,同时编译器忽略掉无法识别的警告名。
@SuppressWarnings(“unchecked”)
10.5、自定义注解
自定义注解类编写的一些规则:
1. Annotation型定义为@interface, 所有的Annotation会自动继承java.lang.Annotation这一接口,并且不能再去继承别的类或是接口.
2. 参数成员只能用public或默认(default)这两个访问权修饰
3. 参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和String、Enum、Class、annotations等数据类型,以及这一些类型的数组.
4. 要获取类方法和字段的注解信息,必须通过Java的反射技术来获取 Annotation对象,因为你除此之外没有别的获取注解对象的方法
5. 注解也可以没有定义成员, 不过这样注解就没啥用了
PS:自定义注解需要使用到元注解
10.6、实例
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 水果名称注解
*/
@Target(FIELD)
@Retention(RUNTIME)
@Documented
public @interface FruitName {
String value() default "";
}
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 水果颜色注解
*/
@Target(FIELD)
@Retention(RUNTIME)
@Documented
public @interface FruitColor {
/**
* 颜色枚举
*/
public enum Color{ BLUE,RED,GREEN};
/**
* 颜色属性
*/
Color fruitColor() default Color.GREEN;
}
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 水果供应者注解
*/
@Target(FIELD)
@Retention(RUNTIME)
@Documented
public @interface FruitProvider {
/**
* 供应商编号
*/
public int id() default -1;
/**
* 供应商名称
*/
public String name() default "";
/**
* 供应商地址
*/
public String address() default "";
}
import java.lang.reflect.Field;
/**
* 注解处理器
*/
public class FruitInfoUtil {
public static void getFruitInfo(Class<?> clazz){
String strFruitName=" 水果名称:";
String strFruitColor=" 水果颜色:";
String strFruitProvicer="供应商信息:";
Field[] fields = clazz.getDeclaredFields();
for(Field field :fields){
if(field.isAnnotationPresent(FruitName.class)){
FruitName fruitName = (FruitName) field.getAnnotation(FruitName.class);
strFruitName=strFruitName+fruitName.value();
System.out.println(strFruitName);
}
else if(field.isAnnotationPresent(FruitColor.class)){
FruitColor fruitColor= (FruitColor) field.getAnnotation(FruitColor.class);
strFruitColor=strFruitColor+fruitColor.fruitColor().toString();
System.out.println(strFruitColor);
}
else if(field.isAnnotationPresent(FruitProvider.class)){
FruitProvider fruitProvider= (FruitProvider) field.getAnnotation(FruitProvider.class);
strFruitProvicer=" 供应商编号:"+fruitProvider.id()+" 供应商名称:"+fruitProvider.name()+" 供应商地址:"+fruitProvider.address();
System.out.println(strFruitProvicer);
}
}
}
}
import test.FruitColor.Color;
/**
* 注解使用
*/
public class Apple {
@FruitName("Apple")
private String appleName;
@FruitColor(fruitColor=Color.RED)
private String appleColor;
@FruitProvider(id=1,name="陕西红富士集团",address="陕西省西安市延安路89号红富士大厦")
private String appleProvider;
public void setAppleColor(String appleColor) {
this.appleColor = appleColor;
}
public String getAppleColor() {
return appleColor;
}
public void setAppleName(String appleName) {
this.appleName = appleName;
}
public String getAppleName() {
return appleName;
}
public void setAppleProvider(String appleProvider) {
this.appleProvider = appleProvider;
}
public String getAppleProvider() {
return appleProvider;
}
public void displayName(){
System.out.println("水果的名字是:苹果");
}
}
/**
* 输出结果
*/
public class FruitRun {
public static void main(String[] args) {
FruitInfoUtil.getFruitInfo(Apple.class);
}
}
运行结果是:
水果名称:Apple
水果颜色:RED
供应商编号:1 供应商名称:陕西红富士集团 供应商地址:陕西省西安市延安路89号红富士大厦
11、泛型
泛型也就是参数化类型。理解泛型类和泛型方法的区别,参数(T、K、V)和通配符(?)的区别。
11.1、泛型类
在类上定义个泛型
public class Dog<T>{
private T a;
public T get(){
return a;
}
}
11.2、泛型接口
这个跟泛型类是类似的
public interface Dog<T> {
T get();
}
11.3、泛型方法
尽量使用泛型方法而不是泛型类。重点是的声明,与泛型类的主要区别。
public class Dog{
public <T> T get(List<T> list){
return list.get(0);}}
1、静态方法
静态方法无法访问类上定义的泛型。如果静态方法操作的引用数据类型不确定的时候,必须要将泛型定义在方法上,也就是说静态方法要使用泛型的话,必须将静态方法也定义成泛型方法。
2、可变参数
public <T> void set(T... arg){
for(T t : arg){
System.out.println(t);
}
}
11.4、类型参数和通配符
类型形参(T、K、V):只能是类类型(eg:Double),不能是简单类型(eg:double)
通配符(?):通配符是类型实参而不是类型形参,它跟String是等价的,可以看成所有类型的父类,是一种真实的类型,理解这里很重要。
11.5、泛型上下边界
泛型上下边界的添加,必须与泛型的声明在一起。
<? extends object>object的所有子类及实现类
<? super String>String的父类
11.6、泛型数组
不能创建一个确切的泛型类型数组,数组的类型不可以是类型变量,除非是采用通配符的方式
List<String>[] list = new ArrayList<String>[10];//编译器报错
List<?>[] list = new ArrayList<?>[10];//正确
List<String>[] list = new ArrayList[10];//正确
12、系统参数
键 | 相关值的描述 |
---|---|
java.version | Java 运行时环境版本 |
java.vendor | Java运行时环境供应商 |
java.vendor.url | Java 供应商的 URL |
java.home | Java 安装目录 |
java.vm.specification.version | Java 虚拟机规范版本 |
java.vm.specification.vendor | Java 虚拟机规范供应商 |
java.vm.specification.name | Java 虚拟机规范名称 |
java.vm.version | Java 虚拟机实现版本 |
java.vm.vendor | Java 虚拟机实现供应商 |
java.vm.name | Java 虚拟机实现名称 |
java.specification.version | Java 运行时环境规范版本 |
java.specification.vendor | Java 运行时环境规范供应商 |
java.specification.name | Java 运行时环境规范名称 |
java.class.version | Java 类格式版本号 |
java.class.path | Java 类路径 |
java.library.path | 加载库时搜索的路径列表 |
java.io.tmpdir | 默认的临时文件路径 |
java.compiler | 要使用的 JIT 编译器的名称 |
java.ext.dirs | 一个或多个扩展目录的路径 |
os.name | 操作系统的名称 |
os.arch | 操作系统的架构 |
os.version | 操作系统的版本 |
file.separator | 文件分隔符(在 UNIX 系统中是“/”) |
path.separator | 路径分隔符(在 UNIX 系统中是“:”) |
line.separator | 行分隔符(在 UNIX 系统中是“/n”) |
user.name | 用户的账户名称 |
user.home | 用户的主目录 |
user.dir | 用户的当前工作目录 |
13、命令行
window环境
java -Dppp=123 -classpath "./xxx.jar;./xxx.jar" com.java.test.main abcd
解析:
ppp是系统属性,可以自行定义,通过-D来带入,后台通过下面的方式获得
System.getProperty("ppp")
-classpath是jdk加载路径
"./xxx.jar;./xxx.jar"
需要加载的jar
com.java.test.main
需要运行的main函数
abcd main函数的参数 也就是args
linux环境
java -Dppp=123 -classpath ./xxx.jar:./xxx.jar com.java.test.main abcd
解析:
与window主要区别就是 ./xxx.jar:./xxx.jar
中的冒号:
14、斜杠/和反斜杠\
window环境
E:\\file.txt
E://file.txt
E:/file.txt
三者等价