java专项练习 - Touale Cula's Blog
  1. Math.*
    ceil:大于等于 x,并且与它最接近的整数。
    floor:小于等于 x,且与 x 最接近的整数。

Math.ceil(d1)
ceil 方法上有这么一段注释:If the argument value is less than zero but greater than -1.0, then the result is negative zero
如果参数小于0且大于-1.0,结果为 -0

Math.floor(d1)
ceil 和 floor 方法 上都有一句话:If the argument is NaN or an infinity or positive zero or negative zero, then the result is the same as the argument,意思为:如果参数是 NaN、无穷、正 0、负 0,那么结果与参数相同,


  1. 关于Collecttion


  1. 数据类型的转换

数据类型的转换,分为自动转换和强制转换。自动转换是程序在执行过程中 “ 悄然 ” 进行的转换,不需要用户提前声明,一般是从位数低的类型向位数高的类型转换;

byte,short,char-> int -> long -> float -> double


  1. 代码执行顺序
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    1. class StaticStuff
    2 {
    3. static int x = 10;
    4.
    5. static { x += 5; }
    6.
    7. public static void main(String args[])
    8. {
    9. System.out.println(“x = ” + StaticStuff .x);
    10. }
    11. static
    12. {x /= 3; }
    13.}

代码编译并执行,输出结果 x = 5.

正常类的加载顺序:静态变量/静态代码块 -> main方法 -> 非静态变量/代码块 -> 构造方法
静态代码块与静态变量的执行顺序同代码定义的顺序;非静态变量与代码块的执行顺序同代码执行顺序


  1. switch()的参数类型

switch语句后的控制表达式只能是short、char、int、long整数类型和枚举类型,不能是float,double和boolean类型。String类型是java7开始支持。


  1. 输出结果
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public class B
    {
    public static B t1 = new B();
    public static B t2 = new B();
    {
    System.out.println("构造块");
    }
    static
    {
    System.out.println("静态块");
    }
    public static void main(String[] args)
    {
    B t = new B();
    }
    }
    构造块 构造块 静态块 构造块

  1. yield

一个线程调用yield方法,可以使具有相同优先级线程获得处理器

yiled方法属于高风亮节的行为,这个坑位我不上了,后面跟我同级别的先上厕所。这样比较好记!


  1. 多态的作用()

提高可重用性

扩展代码模块

没有隐藏细节,隐藏细节应该是封装干的事情吧


  1. session 和 cookie

session用来表示用户会话,session对象在服务端维护,一般tomcat设定session生命周期为30分钟,超时将失效,也可以主动设置无效;

cookie存放在客户端,可以分为内存cookie和磁盘cookie。内存cookie在浏览器关闭后消失,磁盘cookie超时后消失。当浏览器发送请求时,将自动发送对应cookie信息,前提是请求url满足cookie路径; 3.可以将sessionId存放在cookie中,也可以通过重写url将sessionId拼接在url。因此可以查看浏览器cookie或地址栏url看到sessionId;


  1. 顺序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class Example extends Thread{
@Override

public void run(){

try {

Thread.sleep(1000);

} catch (InterruptedException e){

e.printStackTrace();

}

System. out .print( "run" );

}

public static void main(String[] args){

Example example= new Example();

example.run();

System. out .print( "main" );

}
}

run main

好坑

因为Example的run方法里面休眠了100ms,在当今电脑计算性能过剩的时代,如果是多线程启动,main方法肯定会打印出了main。

为啥是runmain而不是mainrun呢?

因为启动线程是调用start方法。
把线程的run方法当普通方法,就直接用实例.run()执行就好了。
没有看到start。所以是普通方法调用。


  1. 顺序
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    public class HelloB extends HelloA 
    {
    public HelloB()
    {
    }
    {
    System.out.println("I’m B class");
    }
    static
    {
    System.out.println("static B");
    }
    public static void main(String[] args)
    {
    new HelloB();
    }
    }
    class HelloA
    {
    public HelloA()
    {
    }
    {
    System.out.println("I’m A class");
    }
    static
    {
    System.out.println("static A");
    }
    }

当涉及到继承时,按照如下顺序执行:
1、执行父类的静态代码块
static {
System.out.println(“static A”);
}
输出:static A
2、执行子类的静态代码块
static {
System.out.println(“static B”);
}
输出:static B
3、执行父类的构造代码块
{
System.out.println(“I’m A class”);
}
输出:I’m A class
4、执行父类的构造函数
public HelloA() {
}
输出:无
5、执行子类的构造代码块
{
System.out.println(“I’m B class”);
}
输出:I’m B class
6、执行子类的构造函数
public HelloB() {
}
输出:无


  1. 要导入java/awt/event下面的所有类

只能是import java.awt.event.*


  1. 正确的方法声明

protected abstract void f1(); // 抽象方法只可以被public 和 protected修饰;

private void f1() {}

static final void fq(){} // static final 可以表达在一起来修饰方法,表示是该方法是静态的不可重写的方法

public final void f1() {}


  1. 运算符>>和>>>

表示右移,如果该数为正,则高位补0,若为负数,则高位补1。如:int i=15; i>>2的结果是3,移出的部分将被抛弃。

转为二进制的形式可能更好理解,0000 1111(15)右移2位的结果是0000 0011(3),0001 1010(18)右移3位的结果是0000 0011(3)。

表示是带符号的右移:按照二进制把数字右移指定数位,符号位为正补零,符号位负补一,低位直接移除。

表示无符号的右移:按照二进制把数字右移指定数位,高位直接补零,低位移除。


  1. catch块和finally块不可以同时省略

  1. final

final修饰符,可以修饰类,方法,变量,不能修饰接口
final修饰的类不可以被继承
final修饰的方法不可以被覆盖
final修饰的变量为常量。只能赋值一次
一般final化的成员变量也会静态化


  1. 代码判断
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    class Person {
    String name = "No name";
    public Person(String nm) {
    name = nm;
    }
    }
    class Employee extends Person {
    String empID = "0000";
    public Employee(String id) {
    empID = id;
    }
    }
    public class Test {
    public static void main(String args[]) {
    Employee e = new Employee("123");
    System.out.println(e.empID);
    }
    }

编译报错

父类没有无参的构造函数,所以子类需要在自己的构造函数中显式调用父类的构造函数,


  1. abstract

抽象类中有抽象方法,需要被实现,不能实例化。
可以被继承,如果不继承,里面的抽象方法就没意思了。
子类不一定为抽象类,可以是,也可以不是。
抽象类不仅可以被继承,还可以直接拿来使用的,当然,这个使用是拿来声明,而不是实例化,因为抽象类不能实例化,但可以声明使用。就像接口一样。
可以被抽象类继承


  1. Object类

A synchronized Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
B C D 都是Object类中的方法
notify(): 是唤醒一个正在等待该对象的线程。
notifyAll(): 唤醒所有正在等待该对象的线程。
E sleep 是Thread类中的方法

wait 和 sleep的区别:
wait指线程处于进入等待状态,形象地说明为“等待使用CPU”,此时线程不占用任何资源,不增加时间限制。
sleep指线程被调用时,占着CPU不工作,形象地说明为“占着CPU睡觉”,此时,系统的CPU部分资源被占用,其他线程无法进入,会增加时间限制。


  1. HashMap和Hashtable

HashMap和Hashtable都是典型的Map实现

Hashtable在实现Map接口时保证了线程安全性,而HashMap则是非线程安全的。所以,Hashtable的性能不如HashMap,因为为了保证线程安全它牺牲了一些性能。因此选项B错误

Hashtable不允许存入null,无论是以null作为key或value,都会引发异常。而HashMap是允许存入null的,无论是以null作为key或value,都是可以的。


  1. final

1.final修饰变量,则等同于常量
2.final修饰方法中的参数,称为最终参数。
3.final修饰类,则类不能被继承
4.final修饰方法,则方法不能被重写。
5.final 不能修饰抽象类
6.final修饰的方法可以被重载 但不能被重写


  1. Java中参数传递

在方法中,修改一个基础类型的参数不会影响原始参数值

在方法中,改变一个对象参数的引用不会影响到原始引用

1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(String []args){
User rabbiter = new User();
rabbiter.setName("rabbiter");
func(rabbiter);
System.out.println(rabbiter.getName());
}
static void func(User user){
user = new User();
user.setName("zhangsan");
}

//输出结果
rabbiter

在方法中,修改一个对象的属性会影响原始对象参数

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String []args){
User rabbiter = new User();
rabbiter.setName("rabbiter");
func(rabbiter);
System.out.println(rabbiter.getName());
}
static void func(User user){
user.setName("zhangsan");
}

//输出结果
zhangsan

在方法中,修改集合和Maps的元素不会影响原始集合参数
集合和Maps都是对象 ,


  1. java object

Object中没有copy方法
clone可以


  1. final、finally、finalize三个关键字的区别

final:可用来定义变量、方法传入的参数、类、方法。
finally:只能跟在try/catch语句中,并且附带一个语句块,表示最后执行。
finalize:是垃圾回收器操作的运行机制中的一部分,进行垃圾回收器操作时会调用finalize方法,因为finalize方法是object的方法,所以每个类都有这个方法并且可以重写这个方法,在这个方法里实现释放系统资源及其他清理工作,JVM不保证此方法总被调用。


  1. sblj

class类是Object的派生类

每个类都使用Object类作为超类,而final修饰的类不能被继承

String类是一个final类

Class类可以装载其它类


  1. 线程共享

私有:java虚拟机栈,程序计数器,本地方法栈
共享:java堆,方法区


  1. 线程安全

线程同步:喂,SHE
喂(Vector)
S(Stack)
H(hashtable)
E(enumeration)


  1. 变量及其范围

类的成员变量包括实例变量和类变量(静态变量),成员方法包括实例方法和类方法(静态方法)

类变量(静态变量)用关键字static声明

方法中的局部变量在方法被调用加载时开始入栈时创建,方法入栈创建栈帧包括局部变量表操作数栈,局部变量表存放局部变量,并非在执行该方法时被创建

局部变量在使用前必须被初始化


  1. /

Java中/是取整,别和数学里的搞混了


  1. 不属于JVM堆内存中的区域

常量池

jvm堆分为:新生代(一般是一个Eden区,两个Survivor区),老年代(old区)。
常量池属于 PermGen(方法区)


  1. Integer,string

String s = “abc”:通过字面量赋值创建字符串。则将栈中的引用直接指向该字符串,如不存在,则在常量池中生成一个字符串,再将栈中的引用指向该字符串
String s = “a”+“bc”:编译阶段会直接将“a”和“bc”结合成“abc”,这时如果方法区已存在“abc”,则将s的引用指向该字符串,如不存在,则在方法区中生成字符串“abc”对象,然后再将s的引用指向该字符串
String s = “a” + new String(“bc”):栈中先创建一个”a”字符串常量,再创建一个”bc”字符串常量,编译阶段不会进行拼接,在运行阶段拼接成”abc”字符串常量并将s的引用指向它,效果相当于String s = new String(“abc”),只有’+’两边都是字符串常量才会在编译阶段优化

Integer的范围是-128~127,如果超出范围的话会新建一个对象,否则就是使用内存中的那个对象。

String str=new String(“abc”)和String str=”abc”的字符串“abc”都是存放在堆中,而不是存在栈中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Test{
public static void main(String args[]){
String s1=new String("abc");//直接在堆中生成新的“abc”
String s2=new String("abc");//直接在堆中生成新的“abc”
String s3="abc";//先去“字符数据池”搜索时候有“abc”这个字符串,如果有,则

将字符串的首地址赋值给s3,如果没有,则在“字符数据池”中生成一个新的字符串“abc”并且将首地

址赋值给s3;
String s4="abc";//去“字符数据池”搜索时发现了上一步生成的“abc”这个字符串

,把该字符串首地址赋值给s4,这时其实s3和s4指向同一个字符数据池中的“abc”
System.out.println(s1==s2);
System.out.println(s1==s3);
System.out.println(s2==s3);
System.out.println(s3==s4);
}
}

结果:
false
fasle
false
true

  1. java程序内存泄露的最直接表现

程序抛内存溢出的Exception

java是自动管理内存的,通常情况下程序运行到稳定状态,内存大小也达到一个 基本稳定的值
但是内存泄露导致Gc不能回收泄露的垃圾,内存不断变大.
最终超出内存界限,抛出OutOfMemoryExpection

FullGC 是老年代内存空间不足的时候,才会触发的,老年代一般是生命周期较长的对象或者大对象,频繁的 FullGC 不会可能会影响程序性能(因为内存回收需要消耗CPU等资源),但是并不会直接导致内存泄漏。

JVM奔溃的可能是内存溢出引起的,也可能是其他导致 JVM崩溃的操作,例如设置了错误的JVM参数等。


  1. java 类加载器

1)Bootstrap ClassLoader

负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类

2)Extension ClassLoader

负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包

3)App ClassLoader

负责记载classpath中指定的jar包及目录中class

4)Custom ClassLoader

属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader


  1. 在WEB开发中实现会话跟踪实现

有四种方法可以实现会话跟踪技术:URL重写、隐藏表单域、Cookie、Session。
1).隐藏表单域:,非常适合步需要大量数据存储的会话应用。
2).URL 重写:URL 可以在后面附加参数,和服务器的请求一起发送,这些参数为名字/值对。
3).Cookie:一个 Cookie 是一个小的,已命名数据元素。服务器使用 SET-Cookie 头标将它作为 HTTP
响应的一部分传送到客户端,客户端被请求保存 Cookie 值,在对同一服务器的后续请求使用一个
Cookie 头标将之返回到服务器。与其它技术比较,Cookie 的一个优点是在浏览器会话结束后,甚至
在客户端计算机重启后它仍可以保留其值
4).Session:使用 setAttribute(String str,Object obj)方法将对象捆绑到一个会话