Java 基础知识(基础知识回顾&&基础知识疑难点总结)
1.面向对象和面向过程的区别
面向过程:面向过程性能比面向对象高。类调用时需要实例化,开销比较大,比较消耗资源,所以当性能是最重要的考量因素的时候,比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发。
面向对象 :面向对象易维护、易复用、易扩展。 因为面向对象有封装、继承、多态性的特性,所以可以设计出低耦合的系统,使系统更加灵活、更加易于维护。但是,面向对象性能比面向过程低。
2. Java 语言有哪些特点?
(1)面向对象(封装,继承,多态);(2)平台无关性( Java 虚拟机实现平台无关性);(3)可靠性、安全性;(4)支持多线程;(5)支持网络编程....
3.关于 JVM JDK 和 JRE
字节码(即扩展名为 .class 的文件),面向虚拟机。Java 语言通过字节码的方式,一定程度上解决了传统解释型语言执行效率低,可移植性的问题。“一次编译,随时可运行”
JIT 编译器,而JIT 属于运行时编译:当 JIT 编译器完成第一次编译后,其会将字节码对应的机器码保存下来,下次可以直接使用。
JDK:功能齐全的Java SDK。它拥有JRE(JVM、Java类库等,只能运行已编译程序)所拥有的一切,还有编译器(javac)和工具(如javadoc和jdb)。它能够创建和编译程序。
4.Java和C++
1.都是面向对象的语言,都支持封装、继承和多态
2.Java 不提供指针来直接访问内存,程序内存更加安全
3.Java 的类是单继承的,C++ 支持多重继承;虽然 Java 的类不可以多继承,但是接口可以多继承。
4.Java 有自动内存管理机制,不需要程序员手动释放无用内存
5.字符型常量和字符串常量的区别?
1.形式上: 字符常量是单引号引起的一个字符; 字符串常量是双引号引起的若干个字符
2.含义上: 字符常量相当于一个整型值( ASCII 值),可以参加表达式运算; 字符串常量代表一个地址值(该字符串在内存中存放位置)
3.占内存大小:字符常量只占2个字节; 字符串常量占若干个字节(至少一个字符结束标志) (注意: char在Java中占两个字节)
6. 重载和重写的区别
重载:发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同,发生在编译时。
重写:发生在父子类中,方法名、参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类;如果父类方法访问修饰符为 private 则子类就不能重写该方法。
(*)7.Java 面向对象编程三大特性: 封装 继承 多态
封装
封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了。
继承
继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码。
关于继承如下 3 点请记住:
子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和方法子类是无法访问,只是拥有。
子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
子类可以用自己的方式实现父类的方法。(以后介绍)。
多态
所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。
在Java中有两种形式可以实现多态:继承(多个子类对同一方法的重写)和接口(实现接口并覆盖接口中同一方法)。
(*)8.String StringBuffer 和 StringBuilder 的区别是什么? String 为什么是不可变的?
(1)可变性
String不可变final,StringBuilder 与 StringBuffer 可变。
String 类中使用 final 关键字修饰字符数组来保存字符串,private final char value[],所以 String 对象是不可变的。而StringBuilder 与 StringBuffer 都继承自AbstractStringBuilder 类,在 AbstractStringBuilder 中也是使用字符数组保存字符串char[]value 但是没有用 final 关键字修饰,所以这两种对象都是可变的。StringBuilder 与 StringBuffer 的构造方法都是调用父类构造方法也就是 AbstractStringBuilder 实现的。
(2)线程安全性
StringBuffer、String安全,StringBuilder不安全
String 中的对象是不可变的,也就可以理解为常量,String线程安全。AbstractStringBuilder 是 StringBuilder 与 StringBuffer 的公共父类,定义了一些字符串的基本操作,如 expandCapacity、append、insert、indexOf 等公共方法。StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。
(3)性能
StringBuilder>StringBuffer>String
每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。
对于三者使用的总结:
操作少量的数据: 适用String
单线程操作字符串缓冲区下操作大量数据: 适用StringBuilder
多线程操作字符串缓冲区下操作大量数据: 适用StringBuffer
9.自动装箱与拆箱
装箱:将基本类型用它们对应的引用类型包装起来;int转成Integer
拆箱:将包装类型转换为基本数据类型;
10.在一个静态方法内调用一个非静态成员为什么是非法的?
由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员。
11.在 Java 中定义一个不做事且没有参数的构造方法的作用
如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用 super() 来调用父类中特定的构造方法,则编译时将发生错误,因为 Java 程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。
(**)12.抽象类和接口的区别:
https://blog.csdn.net/qq_15237565/article/details/79802565
1.抽象类主要是用来抽象类别,接口主要是用来抽象方法功能。当你关注事物的本质的时候,请用抽象类;当你关注一种操作的时候,用接口。
2.一个类可以实现多个接口,但只能实现一个抽象类。
3.接口方法默认修饰符是public,抽象方法可以有public、protected和default这些修饰符。
4.接口中除了static、final变量,不能有其他变量,而抽象类中则不一定。
5.接口里面的方法只能声明,不能有具体的实现。这说明接口是设计的结果,抽象类是重构的结果。
6.抽象类里面的抽象方法必须全部被子类实现,如果子类不能全部实现,那么子类必须也是抽象类。接口里面的方法也必须全部被子类实现,如果子类不能实现那么子类必须是抽象类。
13.成员变量与局部变量的区别有那些?
1.从语法形式上看:成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数;成员变量可以被 public,private,static 等修饰符所修饰,而局部变量不能被访问控制修饰符及 static 所修饰;但是,成员变量和局部变量都能被 final 所修饰。
2.从变量在内存中的存储方式来看:如果成员变量是使用static修饰的,那么这个成员变量是属于类的,如果没有使用static修饰,这个成员变量是属于实例的。而对象存在于堆内存,局部变量则存在于栈内存。
3.从变量在内存中的生存时间上看:成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。
4.成员变量如果没有被赋初值:则会自动以类型的默认值而赋值(一种情况例外:被 final 修饰的成员变量也必须显式地赋值),而局部变量则不会自动赋值。
14. 创建一个对象用什么运算符?对象实例与对象引用有何不同?
new运算符,new创建对象实例(对象实例在堆内存中),对象引用指向对象实例(对象引用存放在栈内存中)。一个对象引用可以指向0个或1个对象(一根绳子可以不系气球,也可以系一个气球);一个对象可以有n个引用指向它(可以用n条绳子系住一个气球)。
15. 一个类的构造方法的作用是什么? 若一个类没有声明构造方法,该程序能正确执行吗? 为什么?构造方法的特性。
主要作用是完成对类对象的初始化工作。可以执行。因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。构造方法有哪些特性?(1)名字与类名相同。(2)没有返回值,但不能用void声明构造函数。(3)生成类的对象时自动执行,无需调用。
16. 对象的相等与指向他们的引用相等,两者有什么不同?
对象的相等,比的是内存中存放的内容是否相等。而引用相等,比较的是他们指向的内存地址是否相等。
17.在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?
帮助子类做初始化工作。
(**)18.== 与 equals(重要)
==:它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象(基本数据类型==比较的是值,引用数据类型==比较的是内存地址)。
equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:
情况1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。
情况2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来比较两个对象的内容是否相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。
说明:
String 中的 equals 方法是被重写过的,因为 object 的 equals 方法是比较的对象的内存地址,而 String 的 equals 方法比较的是对象的值。
当创建 String 类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个 String 对象。
public class Main {
public static void main(String[] args) {
String a = new String("ab");//a为一个引用
String b = new String("ab");//b为另一个引用,对象的内容相同
String aa = "ab";//放入常量池中
String bb = "ab";//从常量池中查找
System.out.println("aa==bb?" + (aa == bb));//true
System.out.println("a==b?"+(a==b));//false
System.out.println("aEqb?"+a.equals(b));//true
System.out.println("42==42.0"+(42 == 42.0));//true
}
}
(**)19.hashCode 与 equals (重要)
面试官可能会问你:“你重写过 hashcode 和 equals 么,为什么重写equals时必须重写hashCode方法?”
hashCode()介绍
hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode() 函数。
散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用到了散列码!(可以快速找到所需要的对象)
为什么要有 hashCode?
我们先以“HashSet 如何检查重复”为例子来说明为什么要有 hashCode: 当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对象加入的位置,同时也会与其他已经加入的对象的 hashcode 值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 equals()方法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。(摘自我的Java启蒙书《Head first java》第二版)。这样我们就大大减少了 equals 的次数,相应就大大提高了执行速度。解决冲突的办法包括了开放定址法(线性探测再散列、二次探测再散列、伪随机探测再散列)、再哈希法以及链地址法。
通过以上我们可以看出:hashCode() 的作用就是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。**hashCode() 在散列表中才有用,在其它情况下没用。**在散列表中hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置。
hashCode()与equals()的相关规定
1.如果两个对象相等,则hashcode一定也是相同的
2.两个对象相等,对两个对象分别调用equals方法都返回true
3.两个对象有相同的hashcode值,它们也不一定是相等的
4.因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖
5.hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)
20.为什么Java中只有值传递?
按值调用(call by value)表示方法接收的是调用者提供的值,而按引用调用(call by reference)表示方法接收的是调用者提供的变量地址。一个方法可以修改传递引用所对应的变量值,而不能修改传递值调用所对应的变量值。
Java程序设计语言对对象采用的不是引用调用,实际上,对象引用是按 值传递的。
下面再总结一下Java中方法参数的使用情况:
1.一个方法不能修改一个基本数据类型的参数(即数值型或布尔型)。
2.一个方法可以改变一个对象参数的状态。
3.一个方法不能让对象参数引用一个新的对象。
public static void main(String[] args) {
//Java程序设计语言总是采用按值调用。也就是说,方法得到的是所有参数值的一个拷贝,
// 也就是说,方法不能修改传递给它的任何参数变量的内容。
int num1 = 10;
int num2 = 20;
swap(num1, num2);
System.out.println("Main方法中 num1:" + num1);
System.out.println("Main方法中 num2:" + num2);
// 通过 example2 我们已经看到,实现一个改变对象参数状态的方法并不是一件难事。
// 理由很简单,方法得到的是对象引用的拷贝,对象引用及其他的拷贝同时引用同一个对象。
int[] arra = {1, 2, 3, 4, 5};
System.out.println(arra[0]);
change(arra);
System.out.println(arra[0]);
Student s1 = new Student("小张");
Student s2 = new Student("小李");
swap01(s1,s2);
System.out.println("Main s1"+s1.getName());
System.out.println("Main s2"+s2.getName());
}
private static void swap01(Student s1, Student s2) {
Student temp = s1;
s1 = s2;
s2= temp;
System.out.println("swap s1"+s1.getName());
System.out.println("swap s2"+s2.getName());
}
private static void change(int[] arra) {
arra[0] = 0;
}
private static void swap(int num1, int num2) {
int tmp = num1;
num1 = num2;
num2 = tmp;
System.out.println("Swap方法中 num1:" + num1);
System.out.println("Swap方法中 num2:" + num2);
}}
21.简述线程、程序、进程的基本概念。以及他们之间关系是什么?
进程是资源分配的基本单位,线程是独立调度的基本单位,一个进程包含一个或者多个线程,程序是包含指令和数据的文件,是静态的代码,存储于数据存储设备之中。其他连这都是动态的。进程是独立的,线程是不一定的。从拥有资源、独立调度、系统开销和通信机制进行区别。
Ⅰ拥有资源
进程是资源分配的基本单位,但是线程不拥有资源,线程可以访问隶属进程的资源。
Ⅱ调度
线程是独立调度的基本单位,在同一进程中,线程的切换不会引起进程切换,从一个进程中的线程切换到另一个进程中的线程时,会引起进程切换。
Ⅲ 系统开销
由于创建或撤销进程时,系统都要为之分配或回收资源,如内存空间、I/O 设备等,所付出的开销远大于创建或撤销线程时的开销。类似地,在进行进程切换时,涉及当前执行进程 CPU 环境的保存及新调度进程 CPU 环境的设置,而线程切换时只需保存和设置少量寄存器内容,开销很小。
Ⅳ通信方面
线程间可以通过直接读写同一进程中的数据进行通信,但是进程通信需要借助 IPC。
22.线程有哪些基本状态?
进程的五种状态:新建、就绪、运行、等待、终止。
(1)运行态一一等待态:等待使用资源或某事件发生,如等待外设传输;等待人工干预。
(2)等待态一一就绪态:资源得到满足或某事件己经发生,如外设传输结束;人工干预完成。
(3)运行态一一就绪态:运行时间片到,或出现有更高优先权进程。
(4)就绪态一一运行态:CPU空闲时被调度选中一个就绪进程执行。
线程的六种状态:初始、运行、阻塞、等待、超时等待以及终止。
线程创建之后它将处于 NEW(新建) 状态,调用 start() 方法后开始运行,线程这时候处于 READY(可运行) 状态。可运行状态的线程获得了 cpu 时间片(timeslice)后就处于 RUNNING(运行) 状态。
操作系统隐藏 Java虚拟机(JVM)中的 RUNNABLE 和 RUNNING 状态,它只能看到 RUNNABLE 状态,所以 Java 系统一般将这两个状态统称为 RUNNABLE(运行中) 状态 。
当线程执行 wait()方法之后,线程进入 **WAITING(等待)**状态。进入等待状态的线程需要依靠其他线程的通知才能够返回到运行状态,而 TIME_WAITING(超时等待) 状态相当于在等待状态的基础上增加了超时限制,比如通过 sleep(long millis)方法或 wait(long millis)方法可以将 Java 线程置于 TIMED WAITING 状态。当超时时间到达后 Java 线程将会返回到 RUNNABLE 状态。当线程调用同步方法时,在没有获取到锁的情况下,线程将会进入到 BLOCKED(阻塞) 状态。线程在执行 Runnable 的run()方法之后将会进入到 TERMINATED(终止)状态。
23.关于 final 关键字的一些总结
final关键字主要用在三个地方:变量、方法、类。
1.对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。
2.当用final修饰一个类时,表明这个类不能被继承。final类中的所有成员方法都会被隐式地指定为final方法。
3.使用final方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。
24.Java 中的异常处理
24.1.
在 Java 中,所有的异常都有一个共同的祖先java.lang包中的 Throwable类。Throwable: 有两个重要的子类:Exception(异常) 和 Error(错误) 。
Exception(异常):是程序本身可以处理的异常;RuntimeException:除个零,下标地址越界。IOExecption:输入输出异常。Error(错误):是程序无法处理的错误。错误是指发生于虚拟机自身、或者发生在虚拟机试图执行应用时的错误,包括了StackOverFlowError和OutOfMemoryError。
24.2.异常处理总结
**try块:**用于捕获异常。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。
**catch块:**用于处理try捕获到的异常。
**finally块:**无论是否捕获或处理异常,finally块里的语句都会被执行。当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行。
24.3.在以下4种特殊情况下,finally块不会被执行:
1.在finally语句块第一行发生了异常。 因为在其他行,finally块还是会得到执行
2.在前面的代码中用了System.exit(int)已退出程序。 exit是带参函数 ;若该语句在异常语句之后,finally会执行
3.程序所在的线程死亡。
4.关闭CPU。
注意:当try语句和finally语句中都有return语句时,在方法返回之前,finally语句的内容将被执行,并且finally语句的返回值将会覆盖原始的返回值。
25. Java序列化中如果有些字段不想进行序列化,怎么办?
对于不想进行序列化的变量,使用transient关键字修饰。
transient关键字的作用是:阻止实例中那些用此关键字修饰的变量序列化;当对象被反序列化时,被transient修饰的变量值不会被持久化和恢复。transient只能修饰变量,不能修饰类和方法。
26.获取用键盘输入常用的的两种方法
//方法1:通过 Scanner
Scanner input = new Scanner(System.in);
String s = input.nextLine();
//方法2:通过BufferedReader
BufferedReader input_01 = new BufferedReader(new InputStreamReader(System.in));
String s1 = input_01.readLine();
input.close();
input_01.close();
27.Java 中 IO 流分为几种?BIO,NIO,AIO 有什么区别?
InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。
27.1.Java 中 IO 流分为几种?
按照流的流向分,可以分为输入流和输出流;
按照操作单元划分,可以划分为字节流和字符流;
按照流的角色划分为节点流和处理流。
27.2.BIO,NIO,AIO 有什么区别?
BIO (Blocking I/O): 同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。
NIO (New I/O): NIO是一种同步非阻塞的I/O模型,提供了 Channel , Selector,Buffer等抽象。它支持面向缓冲的、基于通道的I/O操作方法。对于低负载、低并发的应用程序,可以使用同步阻塞I/O来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发。
AIO:异步非阻塞的IO模型。异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。
28.常见关键字总结:static,final,this,super
final 关键字:主要用在三个地方:变量(基本数据类型:初始化无法修改,引用类型:无法改变指向)、方法(继承子类无法修改含义;提高效率)、类(类不能被继承;类中方法默认为final)。
this 关键字:this关键字用于引用类的当前实例,可选的,使代码易读易懂。
super 关键字:super关键字用于从子类访问父类的变量和方法。
两者必须位于首行,且不能出现在static方法中。
static 关键字主要有以下四种使用场景:
存在于存放在 Java 内存区域的方法区。
1.修饰成员变量和成员方法: 被 static 修饰的成员属于类,不属于单个这个类的某个对象,被类中所有对象共享,可以并且建议通过类名调用。被static 声明的成员变量属于静态成员变量,静态变量 存放在 Java 内存区域的方法区。调用格式:类名.静态变量名 类名.静态方法名()
2.静态代码块: 静态代码块定义在类中方法外, 静态代码块在非静态代码块之前执行(静态代码块—>非静态代码块—>构造方法)。 该类不管创建多少对象,静态代码块只执行一次.
3.静态内部类(static修饰类的话只能修饰内部类): 静态内部类与非静态内部类之间存在一个最大的区别: 非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围类,但是静态内部类却没有。没有这个引用就意味着:1. 它的创建是不需要依赖外围类的创建。2. 它不能使用任何外围类的非static成员变量和方法。
4.静态导包(用来导入类中的静态资源,1.5之后的新特性): 格式为:import static 这两个关键字连用可以指定导入某个类中的指定静态资源,并且不需要使用类名调用类中静态成员,可以直接使用类中静态成员变量和成员方法。
29.Collections 工具类和 Arrays 工具类常见方法
1.Collections工具类常用方法:
(1)排序;(2)查找,替换操作;(3)同步控制(不推荐)
(1)排序:
void reverse(List list)//反转
void shuffle(List list)//随机排序
void sort(List list)//按自然排序的升序排序
void sort(List list, Comparator c)//定制排序,由Comparator控制排序逻辑
void swap(List list, int i , int j)//交换两个索引位置的元素
void rotate(List list, int distance)//旋转。当distance为正数时,将list后distance个元素整体移到前面。当distance为负数时,将 list的前distance个元素整体移到后面。
int binarySearch(List list, Object key)//对List进行二分查找,返回索引,注意List必须是有序的
int max(Collection coll)//根据元素的自然顺序,返回最大的元素。 类比int min(Collection coll)
int max(Collection coll, Comparator c)//根据定制排序,返回最大元素,排序规则由Comparatator类控制。类比int min(Collection coll, Comparator c)
void fill(List list, Object obj)//用指定的元素代替指定list中的所有元素。
int frequency(Collection c, Object o)//统计元素出现次数
int indexOfSubList(List list, List target)//统计target在list中第一次出现的索引,找不到则返回-1,类比int lastIndexOfSubList(List source, list target).
boolean replaceAll(List list, Object oldVal, Object newVal), 用新元素替换旧元素
2.Arrays类的常见操作:排序 : sort();查找 : binarySearch();比较: equals();填充 : fill();转列表: asList();转字符串 : toString();复制: copyOf()
2.1.Arrays.sort可对数组进行快速排序,可对数组按照升序排列数组的指定范围。parallelSort按照数字顺序排列指定的数组(并行的)。可以对String进行排序
2.2.binarySerch(二分法查找元素)、equals(比较,元素数量相同,并且相同位置的元素相同。)
Arrays.toString将其转为字符串。
2.3.fill()(以3完全填充,0-2下标处的元素以9填充)、asList(返回由指定数组支持的固定大小的列表 List
private static void copyof() {
// *************复制 copy****************
// copyOf 方法实现数组复制,h为数组,6为复制的长度
int[] h = { 1, 2, 3, 3, 3, 3, 6, 6, 6, };
int i[] = Arrays.copyOf(h, 6);
System.out.println("Arrays.copyOf(h, 6);:");
// 输出结果:123333
for (int j : i) {
System.out.print(j);
}
// 换行
System.out.println();
// copyOfRange将指定数组的指定范围复制到新数组中
int j[] = Arrays.copyOfRange(h, 6, 11);
System.out.println("Arrays.copyOfRange(h, 6, 11):");
// 输出结果66600(h数组只有9个元素这里是从索引6到索引11复制所以不足的就为0)
for (int j2 : j) {
System.out.print(j2);
}
// 换行
System.out.println();
}
29.Java 基础知识疑难点总结
29.1.Arrays.asList使用指南:
使用它将一个数组转换为一个List集合。Arrays.asList() 方法返回的并不是 java.util.ArrayList ,而是 java.util.Arrays 的一个内部类。
String []Array = new String[]{"Apple","Orange","Banana"};
List myList = Arrays.asList(Array);
//上面和下面两者等价。
List mylist_01 = Arrays.asList("Apple","Orange","Banana");
注意:
注意:
1.Arrays.asList()将数组转换为集合后,底层其实还是数组,使用集合的修改方法:add()、remove(object)、clear()会抛出异常。包装类型数组就可以解决这个问题,将int转换为Integer。
Int[] myArray = { 1, 2, 3 };
List myList = Arrays.asList(myArray);
System.out.println(myList.size());//1
System.out.println(myList.get(0));//数组地址值
System.out.println(myList.get(1));//报错:ArrayIndexOutOfBoundsException
2.传递的数组必须是对象数组,而不是基本类型数组。
29.2.如何正确的将数组转换为ArrayList?
最简便的方法(推荐)
List result = new ArrayList<>(Arrays.asList("apple","banana","orange"));
//方法一:超级for循环遍历
for(String t1:result){
System.out.println(t1);
}
//方法二:对于ArrayList来说速度比较快, 用for循环, 以size为条件遍历:
for(int i = 0;i
29.3.Collection.toArray()方法使用的坑&如何反转数组
String [] s= new String[]{
"dog", "lazy", "a", "over", "jumps", "fox", "brown", "quick", "A"
};
List list = Arrays.asList(s);
Collections.reverse(list);
s=list.toArray(new String[0]);//没有指定类型的话会报错
需要说明的是:new String[0]作为Collection.toArray()方法的参数现在使用更好,new String[0]就是起一个模板的作用,指定了返回数组的类型,0是为了节省空间,因为它只是为了说明返回的类型。
30.get和post请求的区别
1. get是从服务器上获取数据,post是向服务器传送数据。
2.get将表单中数据按照name=value的形式,添加到action 所指向的URL 后面,并且两者使用"?"连接,而各个变量之间使用"&"连接;post是将表单中的数据放在HTTP协议的请求头或消息体中,传递到action所指向URL;
3. 对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。
4. get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。但理论上,IIS4中最大量为80KB,IIS5中为100KB。
5. get安全性非常低,post安全性较高。但是执行效率却比Post方法好。
31.Cookie的作用是什么?和Session有什么区别?
Cookie 和 Session都是用来跟踪浏览器用户身份的会话方式,但是两者的应用场景不太一样。
Cookie一般用来保存用户信息,比如①我们在 Cookie 中保存已经登录过得用户信息,下次访问网站的时候页面可以自动帮你登录的一些基本信息给填了;②一般的网站都会有保持登录也就是说下次你再访问网站的时候就不需要重新登录了,这是因为用户登录的时候我们可以存放了一个 Token 在 Cookie 中,下次登录的时候只需要根据 Token 值来查找用户即可(为了安全考虑,重新登录一般要将 Token 重写);③登录一次网站后访问网站其他页面不需要重新登录。Session 的主要作用就是通过服务端记录用户的状态。典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了。
Cookie 数据保存在客户端(浏览器端),Session 数据保存在服务器端。相对来说 Session 安全性更高。如果使用 Cookie 的一些敏感信息不要写入 Cookie 中,最好能将 Cookie 信息加密然后使用到的时候再去服务器端解密。
转载自:https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/Java%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86.md