命令 | 操作符 |
---|---|
切换盘符 | 盘符名: |
查看当前文件夹 | dir |
进入文件夹 | cd 文件夹名 |
返回上一级 | cd .. |
推出到根目录 | cd \ |
清屏 | cls |
JVM(Java Virtual Machine ):Java虚拟机,简称JVM,是运行所有Java程序的假想计算机,是Java程序的运行环境之一,也是Java 最具吸引力的特性之一。我们编写的Java代码,都运行在JVM 之上。
JVM带来的好处——跨平台
任何软件的运行,都必须要运行在操作系统之上,而我们用Java编写的软件可以运行在任何的操作系统上,这个特性称为Java语言的跨平台特性。该特性是由JVM实现的,我们编写的程序运行在JVM上,而JVM运行在操作系统上。每种操作系统上运行的虚拟机不同,但他们可以执行相同的java程序产生相同的效果。
补充:基本类型所占的空间大小是固定的。不会随着硬件变化而变化,这也是java程序更具可移植性的原因之一。
javac 文件名.java
进行编译,编译完成后,在该目录下生成对应的.class
文件。网上下载即可
File->Settings->Editor->Font
修改字体。功能 | 快捷键 |
---|---|
导入包,自动修正代码 | Alt+Enter |
删除光标所在行 | Ctrl+Y |
复制光标所在行的内容,插入光标位置下面 | Ctrl+D |
格式化代码 | Ctrl+Alt+L |
单行注释 | Ctrl+/ |
选中代码注释,多行注释,再按取消注释 | Ctrl+Shift+/ |
移动当前代码行 | Alt+Shift+上下箭头 |
补全代码 | ctrl+. |
File->Settings->keymap->Main menu->code->Completion->Basic
关键字 | 含义 |
---|---|
class | 类 |
public | 公共权限 |
static | 静态的 |
final | 终态的 |
try | try..catch..finally |
catch | |
finally | |
protected | 受保护权限 |
default | 默认的 |
private | 私有权限 |
int | 整型 |
byte | 字节 |
boolean | 布尔 |
true | 是 |
false | 非 |
if | if..else |
else | |
while | while循环,会与do连用 |
char | 字符型 |
long | 长整型 |
float | 浮点型 |
double | 双精度浮点型 |
import | 导包 |
package | 所属包 |
return | 返回 |
this | 当前类的某方法或构造器的隐藏参数 |
super | 父类的引用 |
void | 空 |
extends | 继承 |
interface | 接口 |
implements | 实现 |
instanceof | 测试对象是否为类的实例 |
new | 创建对象或数组 |
null | 引用未指向对象 |
break | 跳出循环 |
continue | 进入下一次循环 |
switch | switch..case |
case | |
for | 两种for循环 |
throw | 抛异常 |
throws | 声明异常 |
short | 短整型 |
native | 由宿主系统实现的方法 |
synchronized | 对线程而言是原子的方法或代码块 |
strictfp | 严格模式 |
transient | 瞬态 |
volatile | 允许多线程访问 |
assert | 查找内部错误 |
abstract | 抽象 |
自己定义的内容,如类名,变量名,方法名。
算术运算符:++、--
逻辑运算符:!
算术运算符:+、-、*、/、%
赋值运算符:=、+=、-=、/=、%=。
比较运算符:==、>、<、>=、<=、!=
逻辑运算符:&&、||
? :
byte b1=1;
byte b2=2;
byte b3=1 + 2; //
byte b4=b1 + b2;// 编译报错
String s1 = "ab";
String news1 = new String("ab");
String s2 = "abc";
String s3 = "a" + "b";
String s4 = s1 + "c";
s1 == s3; //true
s2 == s4; //false
s1 == news1 //false
修饰符 返回值类型 方法名(参数列表){
//代码省略...
return 结果;
}
一种特殊的方法。后边介绍。
方法签名:
重写: 发生在父子类中,方法名、参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类;如果父类方法访问修饰符为 private 则子类就不能重写该方法。
在JDK1.5之后,如果我们定义一个方法需要接受多个参数,并且多个参数类型一致,我们可以对其简化成如下格式:
修饰符 返回值类型 方法名(参数类型... 形参名){ }
其实这个书写完全等价与
修饰符 返回值类型 方法名(参数类型[] 形参名){ }
只是后面这种定义,在调用时必须传递数组,而前者可以直接传递数据即可。
tips: 上述add方法在同一个类中,只能存在一个。因为会发生调用的不确定性
注意:如果在方法书写时,这个方法拥有多参数,参数中包含可变参数,可变参数一定要写在参数列表的末尾位置。
System.out,print()方法,打印基本数据类型会直接打印,打印引用数据类型会调用该类的toString方法,如果没有重写,toString()方法默认打印地址值。其中数组中有个特殊现象,就是char[],因为char[]可以当作字符串,所以直接打印字符串和字符数组都是直接打印内容,其他数组则需要遍历,否则打印地址值。
for循环,注意越界异常。
重点
重点
重点
了解
了解
没有变量名的对象,只用一次的对象,创建后马上使用,用完即不再需要。
基本类型数据不能作为泛型,为了解决这个问题,jdk提供了包装类可以自动装箱和自动拆箱。每个基本类型都可以转换成对应的包装类。
包装类还有一个作用就是可以调用方法进行类型转换,主要是把字符串转换成基本类型。
关于 static
关键字的使用,它可以用来修饰的成员变量和成员方法,被修饰的成员是属于类的,而不是单单是属于某个对象的。也就是说,既然属于类,就可以不靠创建对象来调用了。
当 static
修饰成员变量时,该变量称为类变量。该类的每个对象都共享同一个类变量的值。任何对象都可以更改该类变量的值,但也可以在不创建该类的对象的情况下对类变量进行操作。
当static
修饰成员方法时,该方法称为类方法 。静态方法在声明中有static
,建议使用类名来调用,而不需要创建类的对象。调用方式非常简单。
小贴士:静态方法只能访问静态成员。
被static修饰的成员可以并且建议通过类名直接访问。虽然也可以通过对象名访问静态成员,原因即多个对象均属于一个类,共享使用同一个静态成员,但是不建议,会出现警告信息。
static
修饰的内容:
定义在成员位置,使用static修饰的代码块{ }。
static 关键字,可以修饰变量、方法和代码块。在使用的过程中,其主要目的还是想在不创建对象的情况下,去调用方法。
final: 不可改变。可以用于修饰类、方法和变量。
引用类型的局部变量,被final修饰后,只能指向一个对象,地址不能再更改。但是不影响对象内部的成员变量值的修改,
内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号 。
比如,Person$Heart.class
带具体实现的
父类或者父接口的
匿名的
子类对象。java.lang.Object
类是Java语言中的根类,即所有类的父类。如果一个类没有特别指定父类, 那么默认则继承自Object类。
public String toString()
:返回该对象的字符串表示。toString方法返回该对象的字符串表示,其实该字符串内容就是对象的类型+@+内存地址值。
public boolean equals(Object obj)
:指示其他某个对象是否与此对象“相等”。调用成员方法equals并指定参数为另一个对象,则可以判断这两个对象是否是相同的。这里的“相同”默认方式是比较两个对象的地址值。不然需要重写来满足自己的需求。
在JDK7添加了一个Objects工具类,它提供了一些方法来操作对象,它由一些静态的实用方法组成,这些方法是null-save(空指针安全的)或null-tolerant(容忍空指针的),用于计算对象的hashcode、返回对象的字符串表示形式、比较两个对象。
public static boolean equals(Object a, Object b)
:判断两个对象是否相等。封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了。
public | protected | default(空的) | private | |
---|---|---|---|---|
同一类中 | √ | √ | √ | √ |
同一包中(子类与无关类) | √ | √ | √ | |
不同包的子类 | √ | √ | ||
不同包中的无关类 | √ |
this代表所在类的当前对象的引用(地址值),即对象自己的引用。
记住 :方法被哪个对象调用,方法中的this就代表那个对象。即谁在调用,this就代表谁。
小贴士:无论你与否自定义构造方法,所有的类都有构造方法,因为Java自动提供了一个无参数构造方法,一旦自己定义了构造方法,Java自动提供的默认无参数构造方法就会失效。
JavaBean
是 Java语言编写类的一种标准规范。符合JavaBean
的类,要求类必须是具体的和公共的,并且具有无参数的构造方法,提供用来操作成员变量的set
和get
方法。
public class ClassName{
//成员变量
//构造方法
//无参构造方法【必须】
//有参构造方法【建议】
//成员方法
//getXxx()
//setXxx()
}
继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码。
关于继承如下 3 点请记住:
super :代表父类的存储空间标识(可以理解为父亲的引用)。
this :代表当前对象的引用(谁调用就代表谁)。
子父类中出现了同名的成员变量时,在子类中需要访问父类中非私有成员变量时,需要使用super
关键字,修饰父类成员变量,访问本类成员变量可以直接访问,或加this
关键字,一般不加 。
如果子类父类中出现不重名的成员方法,这时的调用是没有影响的。对象调用方法时,会先在子类中查找有没有对应的方法,若子类中存在就会执行子类中的方法,若子类中不存在就会执行父类中相应的方法。
如果子类父类中出现重名的成员方法,这时的访问是一种特殊情况,叫做方法重写 (Override)。
如果子类重写了父类方法,又想使用父类的原始方法,一样通过super
关键字进行调用即可。
super()
,表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。子类方法覆盖父类方法,必须要保证权限大于等于父类权限。
private(本类中) < (default 默认)(同一个包) < protected(本类和子类) < public(当前项目中)
子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。
只有单继承。顶层父类是Object,所有类默认继承,是为超类。
父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明还有意义,而方法主体则没有存在的意义了。我们把没有方法主体的方法称为抽象方法。Java语法规定,包含抽象方法的类就是抽象类。
使用abstract
关键字修饰方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体。
继承抽象类的子类必须重写父类所有的抽象方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该父类的抽象方法,否则,从最初的父类到最终的子类都不能创建对象,失去意义。
抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。
抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。
抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。
抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。
理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。
所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。
在Java中有两种形式可以实现多态:继承(多个子类对同一方法的重写)和接口(实现接口并覆盖接口中同一方法)。
接口,是Java语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量、构造方法和成员方法,那么接口的内部主要就是封装了方法,包含抽象方法(JDK 7及以前),默认方法和静态方法(JDK 8),私有方法(JDK 9)。
接口的定义,它与定义类方式相似,但是使用 interface
关键字。它也会被编译成.class文件,但一定要明确它并不是类,而是另外一种引用数据类型。
引用数据类型:数组,类,接口,Lamda。
接口的使用,它不能创建对象,但是可以被实现(implements
,类似于被继承)。一个实现接口的类(可以看做是接口的子类),需要实现接口中所有的抽象方法,创建该类对象,就可以调用方法了,否则它必须是一个抽象类。
抽象方法:使用abstract
关键字修饰,可以省略,没有方法体。该方法供子类实现使用。
默认方法:使用 default
修饰,不可省略,供子类调用或者子类重写。
可以继承,可以重写,二选一,但是只能通过实现类的对象来调用。
接口中,有多个默认方法时,实现类都可继承使用。如果默认方法有重名的,必须重写一次。
静态方法:使用 static
修饰,供接口直接调用。
静态与.class 文件相关,只能使用接口名调用,不可以通过实现类的类名或者实现类的对象调用。
接口中,存在同名的静态方法并不会冲突,原因是只能通过各自接口名访问静态方法。
私有方法:使用 private
修饰,供接口中的默认方法或者静态方法调用。
如果一个接口中有多个默认方法,并且方法中有重复的内容,那么可以抽取出来,封装到私有方法中,供默认方法去调用。从设计的角度讲,私有的方法是对默认方法和静态方法的辅助。
当一个类,既继承一个父类,又实现若干个接口时,父类中的成员方法与接口中的默认方法重名,子类就近选择执行父类的成员方法。
类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类,也可以称为接口的子类。实现的动作类似继承,格式相仿,只是关键字不同,实现使用 implements
关键字。
非抽象子类实现接口:
一个接口能继承另一个或者多个接口,这和类之间的继承比较相似。接口的继承使用 extends
关键字,子接口继承父接口的方法。如果父接口中的默认方法有重名的,那么子接口需要重写一次。
小贴士:
子接口重写默认方法时,default关键字可以保留。
子类重写默认方法时,default关键字不可以保留。
所属包:java.util.Scanner;
基本使用方法举例:
Scanner sc = new Scanner(System.in);
int i = sc.nextInt();
所属包:java.util.Random;
基本使用方法:
//1. 导包
import java.util.Random;
public class Demo01_Random {
public static void main(String[] args) {
//2. 创建键盘录入数据的对象
Random r = new Random();
for(int i = 0; i < 3; i++){
//3. 随机生成一个数据(0-9)
int number = r.nextInt(10);
//4. 输出数据
System.out.println("number:"+ number);
}
}
}
所属包:java.util.ArrayList;
概念:属于集合的一种,可以看成长度可变的数组对象。支持泛型。
常用方法:
public boolean add(E e)
:将指定的元素添加到此集合的尾部。
public E remove(int index)
:移除此集合中指定位置上的元素。返回被删除的元素。
public E get(int index)
:返回此集合中指定位置上的元素。返回获取的元素。
public int size()
:返回此集合中的元素数。遍历集合时,可以控制索引范围,防止越界。
List自带toString方法,可以直接打印。
所属包:java.lang.String;
所属包:java.util.Arrays;
此类包含用来操作数组的各种方法,比如排序和搜索等。其所有方法均为静态方法,调用起来非常简单。
所属包:java.lang.Math;
包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。其中都是静态方法。
public Date()
:分配Date对象并初始化此对象,以表示分配它的时间(精确到毫秒)。public Date(long date)
:分配Date对象并初始化此对象,以表示自从标准基准时间(称为“历元(epoch)”,即1970年1月1日00:00:00 GMT)以来的指定毫秒数。public long getTime()
把日期对象转换成对应的时间毫秒值。简单来说:使用无参构造,可以自动设置当前系统时间的毫秒时刻;指定long类型的构造参数,可以自定义毫秒时刻。
java.text.DateFormat
是日期/时间格式化子类的抽象类。可以在Date对象与String对象之间进行来回转换。
常用的子类java.text.SimpleDateFormat
。
public SimpleDateFormat(String pattern)
:用给定的模式和默认语言环境的日期格式符号构造SimpleDateFormat。参数pattern是一个字符串,代表日期时间的自定义格式。如"yyyy-MM-dd HH:mm:ss"标识字母(区分大小写) | 含义 |
---|---|
y | 年 |
M | 月 |
d | 日 |
H | 时 |
m | 分 |
s | 秒 |
public String format(Date date)
:将Date对象格式化为字符串。public Date parse(String source)
:将字符串解析为Date对象。Calendar为抽象类,Calendar类在创建对象时并非直接创建,而是通过静态方法创建,返回子类对象:
public static Calendar getInstance()
:使用默认时区和语言环境获得一个日历。常用方法:
public int get(int field)
:返回给定日历字段的值。public void set(int field, int value)
:将给定的日历字段设置为给定值。public abstract void add(int field, int amount)
:根据日历的规则,为给定的日历字段添加或减去指定的时间量。public Date getTime()
:返回一个表示此Calendar时间值(从历元到现在的毫秒偏移量)的Date对象。字段值 | 含义 |
---|---|
YEAR | 年 |
MONTH | 月(从0开始,可以+1使用) |
DAY_OF_MONTH | 月中的天(几号) |
HOUR | 时(12小时制) |
HOUR_OF_DAY | 时(24小时制) |
MINUTE | 分 |
SECOND | 秒 |
DAY_OF_WEEK | 周中的天(周几,周日为1,可以-1使用) |
java.lang.System
类中提供了大量的静态方法,可以获取与系统相关的信息或系统级操作。
public static long currentTimeMillis()
:返回以毫秒为单位的当前时间。public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
:将数组中指定的数据拷贝到另一个数组中。
public StringBuilder()
:构造一个空的StringBuilder容器。public StringBuilder(String str)
:构造一个StringBuilder容器,并将字符串添加进去。
public StringBuilder append(...)
:添加任意类型数据的字符串形式,并返回当前对象自身。append方法具有多种重载形式,可以接收任意类型的参数。任何数据作为参数都会将对应的字符串内容添加到StringBuilder中。public String toString()
:将当前StringBuilder对象转换为String对象。
集合是用来存储数据的容器。数组也是容器,但是数组长度不可变。且一个数组只能存储一种类型的数据。集合只能存储引用类型数据,但基本类型可以通过包装类进行存储。所以集合功能比数据强大。
java.util.List
和java.util.Set
。其中,List
的特点是元素有序、元素可重复。Set
的特点是元素无序,而且不可重复。List
接口的主要实现类有java.util.ArrayList
和java.util.LinkedList
,Set
接口的主要实现类有java.util.HashSet
和java.util.TreeSet
。public boolean add(E e)
: 把给定的对象添加到当前集合中 。public void clear()
:清空集合中所有的元素。public boolean remove(E e)
: 把给定的对象在当前集合中删除。public boolean contains(E e)
: 判断当前集合中是否包含给定的对象。public boolean isEmpty()
: 判断当前集合是否为空。public int size()
: 返回集合中元素的个数。public Object[] toArray()
: 把集合中的元素,存储到数组中。List接口特点:
public void add(int index, E element)
: 将指定的元素,添加到该集合中的指定位置上。public E get(int index)
:返回集合中指定位置的元素。public E remove(int index)
: 移除列表中指定位置的元素, 返回的是被移除的元素。public E set(int index, E element)
:用指定元素替换集合中指定位置的元素,返回值的更新前的元素。java.util.ArrayList
集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList
是最常用的集合。
java.util.LinkedList
集合数据存储的结构是链表结构。方便元素添加、删除的集合。
LinkedList是一个双向链表。
与List
接口不同的是,Set
接口中元素无序,并且都会以某种规则保证存入的元素不出现重复。
java.util.HashSet
是Set
接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序不一致)。java.util.HashSet
底层的实现其实是一个java.util.HashMap
支持。
在JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。而JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。
如果我们往集合中存放自定义的对象,那么保证其唯一,就必须复写hashCode和equals方法建立属于当前对象的比较方式。
java.util.LinkedHashSet
,它是链表和哈希表组合的一个数据存储结构。可以让元素有序,但一般不使用。java.utils.Collections
是集合工具类,用来对集合进行操作。部分方法如下:
public static <T> boolean addAll(Collection<T> c, T... elements)
:往集合中添加一些元素。public static void shuffle(List<?> list) 打乱顺序
:打乱集合顺序。public static <T> void sort(List<T> list)
:将集合中元素按照默认规则排序。public static <T> void sort(List<T> list,Comparator<? super T> )
:将集合中元素按照指定规则排序。
集合中的sort方法是用默认规则进行比较,默认增序,是采用Comparable。
Comparator可能实现比较,通过实现这个接口并实现compare方法。
public int compare(String o1, String o2)
:比较其两个参数的顺序。
两个对象比较的结果有三种:大于,等于,小于。
如果要按照升序排序,
则o1 小于o2,返回(负数),相等返回0,01大于02返回(正数)
如果要按照降序排序
则o1 小于o2,返回(正数),相等返回0,01大于02返回(负数)前减后升序
两种比较器的区别:
Comparable:强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。只能在类中实现compareTo()一次,不能经常修改类的代码实现自己想要的排序。实现此接口的对象列表(和数组)可以通过Collections.sort(和Arrays.sort)进行自动排序,对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。
Comparator强行对某个对象进行整体排序。可以将Comparator 传递给sort方法(如Collections.sort或 Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构(如有序set或有序映射)的顺序,或者为那些没有自然顺序的对象collection提供排序。
在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,JDK专门提供了一个接口java.util.Iterator
。Iterator
接口也是Java集合中的一员,但它与Collection
、Map
接口有所不同,Collection
接口与Map
接口主要用于存储元素,而Iterator
主要用于迭代访问(即遍历)Collection
中的元素,因此Iterator
对象也被称为迭代器。
public Iterator iterator()
: 获取集合对应的迭代器,用来遍历集合中的元素的。
迭代:即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。
Iterator接口的常用方法如下:
public E next()
:返回迭代的下一个元素。public boolean hasNext()
:如果仍有元素可以迭代,则返回 true。增强for循环的底层也是迭代器。增强for循环被叫做语法糖。
Map
中的集合,元素是成对存在的(理解为夫妻)。每个元素由键与值两部分组成,通过键可以找对所对应的值。
Map接口中定义了很多方法,常用的如下:
public V put(K key, V value)
: 把指定的键与指定的值添加到Map集合中。使用put方法时,若指定的键(key)在集合中没有,则没有这个键对应的值,返回null,并把指定的键值添加到集合中;
若指定的键(key)在集合中存在,则返回值为集合中键对应的值(该值为替换前的值),并把指定键所对应的值,替换成指定的新值。
public V remove(Object key)
: 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。
public V get(Object key)
根据指定的键,在Map集合中获取对应的值。
public Set<K> keySet()
: 获取Map集合中所有的键,存储到Set集合中。
public Set<Map.Entry<K,V>> entrySet()
: 获取到Map集合中所有的键值对对象的集合(Set集合)。
public K getKey()
:获取Entry对象中的键。public V getValue()
:获取Entry对象中的值。Map的遍历:
键找值方式:即通过元素中的键,获取键所对应的值
键值对方式:即通过集合中每个键值对(Entry)对象,获取键值对(Entry)对象中的键与值。
例子:
public class HelloJDK9 {
public static void main(String[] args) {
Set<String> str1=Set.of("a","b","c");
//str1.add("c");这里编译的时候不会错,但是执行的时候会报错,因为是不可变的集合
System.out.println(str1);
Map<String,Integer> str2=Map.of("a",1,"b",2);
System.out.println(str2);
List<String> str3=List.of("a","b");
System.out.println(str3);
}
}
需要注意以下两点:
1:of()方法只是Map,List,Set这三个接口的静态方法,其父类接口和子类实现并没有这类方法,比如 HashSet,ArrayList等待;
2:返回的集合是不可变的;
栈:stack,又称堆栈,它是运算受限的线性表,其限制是仅允许在标的一端进行插入和删除操作,不允许在其他任何位置进行添加、查找、删除等操作。
队列:queue,简称队,它同堆栈一样,也是一种运算受限的线性表,其限制是仅允许在表的一端进行插入,而在表的另一端进行删除。
数组:Array,是有序的元素序列,数组是在内存中开辟一段连续的空间,并在此空间存放元素。
查找元素快:通过索引,可以快速访问指定位置的元素。
增删元素慢
链表:linked list,由一系列结点node(链表中每一个元素称为结点)组成,结点可以在运行时i动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
查找元素慢,增删元素快。
二叉树、红黑树等等
修饰符 class 类名<代表泛型的变量> { }
修饰符 <代表泛型的变量> 返回值类型 方法名(参数){ }
修饰符 interface接口名<代表泛型的变量> { }
之前设置泛型的时候,实际上是可以任意设置的,只要是类就可以设置。但是在JAVA的泛型中可以指定一个泛型的上限和下限。
泛型的上限:
类型名称 <? extends 类 > 对象名称
只能接收该类型及其子类
泛型的下限:
类型名称 <? super 类 > 对象名称
只能接收该类型及其父类型
在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。
异常机制其实是帮助我们找到程序中的问题,异常的根类是java.lang.Throwable
,其下有两个子类:java.lang.Error
与java.lang.Exception
,平常所说的异常指java.lang.Exception
。
throw new NullPointerException("要访问的arr数组不存在");
throw new ArrayIndexOutOfBoundsException("该索引在数组中不存在,已超出范围");
关键字throws运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常).
捕获异常:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理。
try{
编写可能会出现异常的代码
}catch(异常类型 e){
处理异常的代码
//记录日志/打印异常信息/继续抛出异常
}
//多个异常的情况
//注意:这种异常处理方式,要求多个catch中的异常不能相同,并且若catch中的多个异常之间有子父类异常的关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。
try{
编写可能会出现异常的代码
}catch(异常类型A e){ 当try中出现A类型异常,就用该catch来捕获.
处理异常的代码
//记录日志/打印异常信息/继续抛出异常
}catch(异常类型B e){ 当try中出现B类型异常,就用该catch来捕获.
处理异常的代码
//记录日志/打印异常信息/继续抛出异常
}
代码无论异常是否发生,都需要执行。
PS:当只有在try或者catch中调用退出JVM的相关方法,此时finally才不会执行,否则finally永远会执行。
异常类如何定义:
java.lang.Exception
。java.lang.RuntimeException
。进程与线程的区别
注意:
线程调度:
计算机通常只有一个CPU时,在任意时刻只能执行一条计算机指令,每一个进程只有获得CPU的使用权才能执行指令。所谓多进程并发运行,从宏观上看,其实是各个进程轮流获得CPU的使用权,分别执行各自的任务。那么,在可运行池中,会有多个线程处于就绪状态等到CPU,JVM就负责了线程的调度。JVM采用的是抢占式调度,没有采用分时调度,因此可以能造成多线程执行结果的的随机性。
Java使用java.lang.Thread
类代表线程,所有的线程对象都必须是Thread类或其子类的实例。每个线程的作用是完成一定的任务,实际上就是执行一段程序流即一段顺序执行的代码。Java使用线程执行体来代表这段程序流。Java中通过继承Thread类来创建并启动多线程的步骤如下:
采用java.lang.Runnable
也是非常常见的一种,我们只需要重写run方法即可。
步骤如下:
总结:
实现Runnable接口比继承Thread类所具有的优势:
同步代码块:synchronized
关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。
synchronized(同步锁){
需要同步操作的代码
}
同步锁:
对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁.
注意:在任何时候,最多允许一个线程拥有同步锁,谁拿到锁就进入代码块,其他的线程只能在外等着(BLOCKED)。
格式:
public synchronized void method(){
可能会产生线程安全问题的代码
}
同步锁是谁?
? 对于非static方法,同步锁就是this。
? 对于static方法,我们使用当前方法所在类的字节码对象(类名.class)。
java.util.concurrent.locks.Lock
机制提供了比synchronized代码块和synchronized方法更广泛的锁定操作,同步代码块/同步方法具有的功能Lock都有,除此之外更强大,更体现面向对象。
Lock锁也称同步锁,加锁与释放锁方法化了,如下:
public void lock()
:加同步锁。public void unlock()
:释放同步锁。什么是等待唤醒机制
这是多个线程间的一种协作机制。谈到线程我们经常想到的是线程间的竞争(race),比如去争夺锁,但这并不是故事的全部,线程间也会有协作机制。
就是在一个线程进行了规定操作后,就进入等待状态(wait()), 等待其他线程执行完他们的指定代码过后 再将其唤醒(notify());在有多个线程进行等待时, 如果需要,可以使用 notifyAll()来唤醒所有的等待线程。
Java里面线程池的顶级接口是java.util.concurrent.Executor
,但是严格意义上讲Executor
并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是java.util.concurrent.ExecutorService
。
Executors类中有个创建线程池的方法如下:
public static ExecutorService newFixedThreadPool(int nThreads)
:返回线程池对象。(创建的是有界线程池,也就是池中的线程个数可以指定最大数量)获取到了一个线程池ExecutorService 对象,那么怎么使用呢,在这里定义了一个使用线程池对象的方法如下:
public Future<?> submit(Runnable task)
:获取线程池中的某一个线程对象,并执行
Future接口:用来记录线程任务执行完毕后产生的结果。线程池创建与使用。
使用线程池中线程对象的步骤:
Lambda表达式的标准格式为:
(参数类型 参数名称) -> { 代码语句 }
格式说明:
->
是新引入的语法格式,代表指向动作。在Lambda标准格式的基础上,使用省略写法的规则为:
Runnable
、Comparator
接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才可以使用Lambda。备注:有且仅有一个抽象方法的接口,称为“函数式接口”。
java.io.File
类是文件和目录路径名的抽象表示,主要用于文件和目录的创建、查找和删除等操作。
public File(String pathname)
:通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。public File(String parent, String child)
:从父路径名字符串和子路径名字符串创建新的 File实例。public File(File parent, String child)
:从父抽象路径名和子路径名字符串创建新的 File实例。一个File对象代表硬盘中实际存在的一个文件或者目录。
无论该路径下是否存在文件或者目录,都不影响File对象的创建。
public String getAbsolutePath()
:返回此File的绝对路径名字符串。
public String getPath()
:将此File转换为路径名字符串。
public String getName()
:返回由此File表示的文件或目录的名称。
public long length()
:返回由此File表示的文件的长度(字节)。
绝对路径:从盘符开始的路径,这是一个完整的路径。
相对路径:相对于项目目录的路径,这是一个便捷的路径,开发中经常使用。
public boolean exists()
:此File表示的文件或目录是否实际存在。
public boolean isDirectory()
:此File表示的是否为目录。
public boolean isFile()
:此File表示的是否为文件。
public boolean createNewFile()
:当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。
public boolean delete()
:删除由此File表示的文件或目录。
public boolean mkdir()
:创建由此File表示的目录。
public boolean mkdirs()
:创建由此File表示的目录,包括任何必需但不存在的父目录。
public String[] list()
:返回一个String数组,表示该File目录中的所有子文件或目录。
public File[] listFiles()
:返回一个File数组,表示该File目录中的所有的子文件或目录。
递归:指在当前方法内调用自己的这种现象。
递归一定要有条件限定,保证递归能够停止下来,次数不要太多,否则会发生栈内存溢出。
根据数据的流向分为:输入流和输出流。
其他设备
上读取到内存
中的流。内存
中写出到其他设备
上的流。格局数据的类型分为:字节流和字符流。
顶层父类:
输入流 | 输出流 | |
---|---|---|
字节流 | 字节输入流 InputStream |
字节输出流 OutputStream |
字符流 | 字符输入流 Reader |
字符输出流 Writer |
缓冲流,也叫高效流,是对4个基本的FileXxx
流的增强,所以也是4个流,按照数据类型分类:
BufferedInputStream
,BufferedOutputStream
BufferedReader
,BufferedWriter
转换流:
java.io.InputStreamReader
,是Reader的子类,是从字节流到字符流的桥梁。它读取字节,并使用指定的字符集将其解码为字符。它的字符集可以由名称指定,也可以接受平台的默认字符集。
InputStreamReader(InputStream in)
: 创建一个使用默认字符集的字符流。InputStreamReader(InputStream in, String charsetName)
: 创建一个指定字符集的字符流。java.io.OutputStreamWriter
,是Writer的子类,是从字符流到字节流的桥梁。使用指定的字符集讲字符编码为字节。它的字符集可以由名称指定,也可以接受平台的默认字符集。
OutputStreamWriter(OutputStream in)
: 创建一个使用默认字符集的字符流。OutputStreamWriter(OutputStream in, String charsetName)
: 创建一个指定字符集的字符流。序列化流:
java.io.ObjectOutputStream
类,将Java对象的原始数据类型写出到文件,实现对象的持久存储。
写出对象方法
public final void writeObject (Object obj)
: 将指定的对象写出。一个对象要想序列化,必须满足两个条件:
java.io.Serializable
接口,Serializable
是一个标记接口,不实现此接口的类将不会使任何状态序列化或反序列化,会抛出NotSerializableException
。transient
关键字修饰。ObjectInputStream反序列化流,将之前使用ObjectOutputStream序列化的原始数据恢复为对象。
如果能找到一个对象的class文件,我们可以进行反序列化操作,调用ObjectInputStream
读取对象的方法:
public final Object readObject ()
: 读取一个对象。对于JVM可以反序列化对象,它必须是能够找到class文件的类。如果找不到该类的class文件,则抛出一个 ClassNotFoundException
异常。
当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操作也会失败,抛出一个InvalidClassException
异常。发生这个异常的原因如下:
Serializable
接口给需要序列化的类,提供了一个序列版本号。serialVersionUID
该版本号的目的在于验证序列化的对象和对应类是否版本匹配。
C/S结构 :全称为Client/Server结构,是指客户端和服务器结构。
B/S结构 :全称为Browser/Server结构,是指浏览器和服务器结构。
TCP:传输控制协议 (Transmission Control Protocol)。TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。
UDP:用户数据报协议(User Datagram Protocol)。UDP协议是一个面向无连接的协议。传输数据时,不需要建立连接,不管对方端服务是否启动,直接将数据、数据源和目的地都封装在数据包中,直接发送。每个数据包的大小限制在64k以内。它是不可靠协议,因为无连接,所以传输速度快,但是容易丢失数据。日常应用中,例如视频会议、QQ聊天等。
原文:https://www.cnblogs.com/buyusan/p/11172787.html