Java基础

知识点

1.==与equals与hashcode
  ==判相等:基本类型直接看数值,引用类型必须指向同一对象(需要注意intcache池)。一基本类型一引用类型则引用类型自动拆箱。
  equals判相等:首先看类里面有没有自定义的equals方法,没有就默认调用Object类的equals方法,先比较两边对象是否相同,比如字符数组和字符串就一点返回flase对对象比较的是地址(基本型先比类型,一样再比大小),对基本数据类型比较值,对String比较是否内容一样(即字符串中的各个字符都一样)。
  hashCode()判相等:hashCode()方法和equals()方法的作用其实是一样的,在Java里都是用来对比两个对象是否相等一致。即我们规定:1.如果equals相等则hashcode一定要相等。2.equals不相等则hashcode一定不相等。应用场景为:因为重写的equals()里一般比较的比较全面比较复杂,这样效率就比较低,而利用hashCode()进行对比,则只要生成一个hash值进行比较就可以了,效率很高。但hashCode()并不是完全可靠,有时候不同的对象他们生成的hashcode也会一样(生成hash值得公式可能存在的问题),所以hashCode()只能说是大部分时候可靠,并不是绝对可靠。

注意:
1.两个对象比较时,本来integer的会有cache,但是如果是new的对象就不在cahce里,直接堆上创建;==一定回false。如果是直接=赋值,两者指向的会是同一堆对象,==回true。
2.一个基本型int和一个对象比较时,基本型和基本型封装型进行“==”运算符的比较,基本型封装型将会自动拆箱变为基本型后再进行比较,因此Integer(0)会自动拆箱为int类型再进行比较,显然返回true;

2.不同访问权限

Java关键字权限
A在类中定义的变量称为类的成员变量,在别的类中可以直接使用局部变量的
B局部变量的作用范围仅仅在定义它的方法内,或者是在定义它的控制流块中
C使用别的类的方法需要通过该类的对象引用方法的名字
D只要没有定义任何构造函数,JVM都会为类生成一个默认构造函数

public和protected都可以作用于子类,但在多态情况下,静态函数调用时编译和运行看左边,所以子父类存在同名静态函数访问的是父类,子类并不能覆盖父类的方法。
static修饰的成员属于类成员,父类字段或方法只能被子类同名字段或方法遮蔽,不能被继承覆盖。

3.因为String是被final修饰的类,所以本身的内容是不会改变的,相当于基本数据类型的值传递.和int一样有cache缓存池,需要注意的是(b+c)==MESSAGE这个语句中是相当于new String(b+c)==MESSAGE 这里new了一个String对象而非在缓存池中取的。

4.Java初始化

Java程序初始化工作可以在许多不同的代码块中来完成,它们的执行顺序如下:
父类的静态变量、父类的静态代码块、子类的静态变量、子类的静态代码块、
父类的非静态变量、父类的非静态代码块、父类的构造函数、
子类的非静态变量、子类的非静态代码块、子类的构造函数。
需要注意的是java继承中对构造函数是不继承的,只是显式或者隐式调用在创建子类的对象的时候,若子类构造函数没有显式调用父类构造函数,就会先调用父类的无参构造函数;若是在子类的构造函数显式调用了父类的构造函数(包括有参的可以),则会先调用刚刚显示调用的父类构造函数。

构造方法没有返回值。

5.被static修饰的变量称为静态变量,静态变量属于整个类,而局部变量属于方法,只在该方法内有效,所以static不能修饰局部变量
类方法中不能直接调用成员变量,因为例外是不能静态方法中引用非静态的域。原因也很简单关于类初始化的过程中,静态域是随着类加载就完成了初始化,而非静态域此时都没有完成初始化,你引用它肯定就出错了。

6.super与this

super出现在继承了父类的子类中。有三种存在方式:
第一种:super.xxx;(xxx为变量名或对象名)
这种方法意义为,获取父类中的名字为xxx的变量或方法引用。
使用这种方法可以直接访问父类中的变量或对象,进行修改赋值等操作
第二种:super.xxx();(xxx为方法名)
这种方法意义为,直接访问并调用父类中的方法。
第三种:super();
这种方法意义为,调用父类的初始化方法,其实就是调用父类中的public xxx()方法

java继承中对构造函数是不继承的,只是显式或者隐式调用

此外,super只能指代其直接父类,在父类中调用super能指代父类的父类。
this表示当前类的对象,由static修饰的方法是由类直接调用,不需要创建对象,所以在static里不能用this.

this()和super()为构造方法,作用是在JVM堆中构建出一个对象。因此避免多次创建对象,同一个方法内只能调用一次this()或super()。同时为了避免操作对象时对象还未构建成功,需要this()和super()的调用在第一行实现【以此来创建对象】,防止异常。即this()必须是构造函数中的第一个可执行语句,但用this调用语句并不需要。而且this是对重载的构造函数调用,super是对父类的构造函数调用

子类与父类:
1.一个java文件里,public 的类只能出现一个,只能出现一个,只能出现一个,否则,不管你用哪一个类名命名文件名编译器都会报错
2.关于多态。子类继承了父类的所有成员,包括private权限的成员变量,但是继承的子类具有私有变量的拥有权但是没有使用权。
3.private的成员变量,根据权限修饰符的访问控制范围,只有在类内部才能被访问,就算是他的子类,也不能访问。
4.子类重写父类方法时,方法的访问权限不能小于原访问权限,在接口中,方法的默认权限就是public,所以子类重写后只能是public

7.Java8的接口方法可以有如下定义

only public, abstract, default, static and strictfp are permitted 接口默认权限是public
故不能用private和protected

8、接口与抽象类

JDK1.7中:
接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。另外,接口和抽象类在方法上有区别:
1.抽象类可以有构造方法,接口中不能有构造方法。
2.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
3.抽象类中可以有普通成员变量,接口中没有普通成员变量,接口里的数据成员必须初始化,且全是常量,不是变量。
4.抽象类中的抽象方法的访问类型可以是public,protected和默认类型,接口只有public
5.抽象类中可以包含静态方法,接口中不能包含静态方法
6.抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型

接口中没有变量,其中变量必须为“public final static”,即为常量。
定义的抽象方法没有实体时候,大括号必须省略。

7.一个类可以实现多个接口,但只能继承一个抽象类。

JDK1.8中
1.抽象方法必须为public或者protectedJDK 1.8以前,抽象类的方法默认访问权限为protected 。JDK 1.8时,抽象类的方法默认访问权限变为default
2.接口中的方法可以用static,default修饰,且二者修饰的方法要求有方法体

9.abstract

对于abstract类的子类来说有两种途径,一种是实现其超类的所有abstract方法;或者是子类也声明为abstract类,将全部实现抽象方法的责任交给它的子类。
基类是抽象类,子类继承父类,但是没有实现基类的抽象方法,那么子类也是抽象类。抽象类不能创建对象,所以在主函数中创建对象编译不会通过。

抽象类不能创建对象,所以在主函数中创建对象编译不会通过。
抽象方法必须为public或者protectedJDK 1.8以前,抽象类的方法默认访问权限为protected 。JDK 1.8时,抽象类的方法默认访问权限变为default

抽象方法没有方法体,有没有方法体看有没有大括号:
  接口中方法的默认修饰符时public abstract,抽象方法可是没有方法体的,没有大括号{}
 jdk1.8新特性,接口中的方法可以用static,default修饰,且二者修饰的方法要求有方法体

abstract 方法必须在abstract类或接口中。

10.java中函数参数传递方式是引用传递

11.string是值传递,stringbuffer是引用传递。

12.Java中if判断

1、Java中,赋值是有返回值的 ,赋什么值,就返回什么值。比如这题,x=y,返回y的值,所以括号里的值是1。
2、Java跟C的区别,C中赋值后会与0进行比较,如果大于0,就认为是true;而Java不会与0比较,而是直接把赋值后的结果放入括号。即if(1)会报错

13.copy

1.Object中没有copy方法

14.前台进程、后台进程

main()函数即主函数,是一个前台线程,前台进程是程序中必须执行完成的,而后台线程则是java中所有前台结束后结束,不管有没有完成,后台线程主要用与内存分配等方面。
后台线程:指为其他线程提供服务的线程,也称为守护线程。JVM的垃圾回收线程就是一个后台线程。 前台线程:是指接受后台线程服务的线程,其实前台后台线程是联系在一起,就像傀儡和幕后操纵者一样的关系。傀儡是前台线程、幕后操纵者是后台线程。由前台线程创建的线程默认也是前台线程。可以通过isDaemon()和setDaemon()方法来判断和设置一个线程是否为后台线程。
jre 判断程序是否执行结束的标准是()所有的前台线程执行完毕

15.java中整型默认的是int,浮点默认的是double.

16.值传递和引用传递:

Java语言 中只有按值传递。但是java方法参数中有两种类型:基本数据类型(Primitive types)和对象引用(Object reference)。所以就有人以为当传递Object时是Call by reference。其实还是传递的这个reference的副本。

call by value不会改变实际参数的数值
call by reference不能改变实际参数的参考地址。
call by reference能改变实际参数的内容。

值传递不可以改变原变量的内容和地址---》原因是java方法的形参传递都是传递原变量的副本,在方法中改变的是副本的值,而不适合原变量的。
引用传递不可以改变原变量的地址,但可以改变原变量的内容---》原因是当副本的引用改变时,原变量 的引用并没有发生变化,当副本改变内容时,由于副本引用指向的是原变量的地址空间,所以,原变量的内容发生变化。

17.关键字和保留字

关键字列表 (依字母排序 共50组):
abstract, assert, boolean, break, byte, case, catch, char, class, const(保留关键字), continue, default, do, double, else, enum, extends, final, finally, float, for, goto(保留关键字), if, implements, import, instanceof, int, interface, long, native, new, package, private, protected, public, return, short, static, strictfp, super, switch, synchronized, this, throw, throws, transient, try, void, volatile, while
保留字列表 (依字母排序 共14组),Java保留字是指现有Java版本尚未使用,但以后版本可能会作为关键字使用:
byValue, cast, false, future, generic, inner, operator, outer, rest, true, var, goto (保留关键字) , const (保留关键字) , null

18.Java中的byte,short,char进行计算时都会提升为int类型。
被fianl修饰的变量不会自动改变类型,当2个final修饰相操作时,结果会根据左边变量的类型而转化。

19.Lanbda表达式的主要作用就是代替匿名内部类的繁琐语法, 它由三部分组成:
(1) 形参列表。形参列表允许省略形参类型。如果形参列表中只有一个参数,甚至连形参列表的圆括号也可以省略。
(2)箭头 (→)。必须通过英文中画线和大于符号组成。
(3)代码块。如果代码块只包含一条语句,Lambda表达式允许省略代码块的花括号,那么那条语句就不要用花括号表示语句结束。Lambda代码块只有一条return语句,甚至可以省略return关键字。Lambda表达式需要返回值,而它的代码块中仅有一套省略了return的语句。Lambda表达式会自动返回这条语句的值。

20.序列化。 使用ObjectOutputStream和ObjectInputStream可以将对象进行传输.声明为static和transient类型的成员数据不能被串行化。因为static代表类的状态, transient代表对象的临时数据。

21.switch结构中没有break;switch case 方法中若,没有break跳出执行则程序就会从第一个匹配上的case一直执行到整个结构结束。
Java switch支持 int及以下(char, short, byte),String, Enum

22.public static void main(String[] args) OR public static void main(String args[])。这是Java规范,这是JVM决定的。java执行程序某个类时,首先执行的就是main方法,而执行方式就是类名+方法名,所以必须是public static,规范要求必须传入一个String[]作为参数,这个String数组的名字无关紧要,这个数组用来装命令行传入main方法的参数用

23.count = count++ 原理是 temp = count; count = count+1 ; count = temp; 因此count始终是0 这仅限于java 与c是不一样的

24.当试图在类方法(也就是静态方法)中调用类的非静态变量时,eclipse 给出了这么一句话 Cannot make a static reference to the non-static field xxx(xxx代表你所写的非静态域的名字)。这句话意思很简单,就是不能静态方法中引用非静态的域。
原因也很简单关于类初始化的过程中,静态域是随着类加载就完成了初始化,而非静态域此时都没有完成初始化,你引用它肯定就出错了。

25.构造函数不止通过new,通过this也可以调用

26.内部类

More问题

1.Java版本特点?

具体来说:Lambda表达式可以···
作者:公众号-Java名企面试吧
链接:https://www.nowcoder.com/discuss/140003
来源:牛客网

Lambda表达式是Java8所引入的新特性之一,其基于函数式接口,以极大地减少代码冗余,并提高代码的可读性。

Java8中引入箭头操作符(也叫Lambda操作符)将Lambda表达式拆分成左右两部分:

左侧:指定Lambda表达式的参数列表;
右侧:指定Lambda表达式所要执行的功能,即Lambda体。


// 1).无参数,无返回值 Runnable r1 = () -> System.out.println("Hello Lambda!"); // 2).有一个参数,无返回值(只有一个参数时,小括号可以省略) Consumer<String> con = (x) -> System.out.println(x); con.accept("Hello Lambda!);

// 1).无参数,无返回值
Runnable r1 = () -> System.out.println("Hello Lambda!");

// 2).有一个参数,无返回值(只有一个参数时,小括号可以省略)
Consumer con = (x) -> System.out.println(x);
con.accept("Hello Lambda!);
2.Java8 Optional类?

3.java反射机制,与classloader的区别
普通的java对象是通过new关键字把对应类的字节码文件用classloader加载到内存,然后创建该对象的。

反射是通过一个名为Class的特殊类,用Class.forName("className");得到类的字节码对象,然后用newInstance()方法在虚拟机内部构造这个对象(针对无参构造函数)。
也就是说反射机制让我们可以先拿到java类对应的字节码对象,然后动态的进行任何可能的操作,

Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。使用反射的主要作用是方便程序的扩展。

4.深拷贝,浅拷贝

浅拷贝就是指两个对象公用一个值,一个的改变了另一个也会随之改变,深拷贝则是两个对象值相等,但是相互独立互不影响。

JAVA对象拷贝分为两种方式,一种是引用拷贝,一种是对象拷贝

引用拷贝:和对象拷贝的不同之处在于,引用拷贝只会生成一个新的对象引用地址,但两个地址其最终指向的还是同一个对象;

对象拷贝:这种方式会重新生成一个新的对象,生成的新对象与原来的对象没有任何关联。

当你只有浅复制的时候,你可以自己写代码来完成深复制。当你只有深复制的时候,你面对浅复制的需求只能哭了。所以这就是为什么C#提供浅复制。所以你自己给item写一个Clone函数就好了。还有,ArrayList是傻逼,请用List

4.父类方法有private修饰,对子类不可见,子类不能覆盖。这时子类方法和父类是两个方法。
final声明的方法是不能被覆盖的,子类覆盖时会报错,除非如上一句,父类使用了private;

线程

1.线程结束的三个原因:
1、run方法执行完成,线程正常结束
2、线程抛出一个未捕获的Exception或者Error
3、直接调用该线程的Stop方法结束线程(不建议使用,容易导致死锁)
不会终止运行的:当一个优先级高的线程进入就绪状态时、当创建一个新线程时,都是抢占,抢不抢得到不知道。当前线程调用sleep()方法或者wait()方法时,只是暂时停止了该线程的运行,不是终止线程,注意题目说的是“终止”,就是完全停止。

2.sleep与wait区别
相同:wait()和sleep()都可以通过interrupt()方法 打断线程的暂停状态 ,从而使线程立刻抛出InterruptedException。
区别:
1.首先,sleep()是Thread类中的方法,而wait()则是Object类中的方法。
2.sleep()方法导致了程序暂停,但是他的监控状态依然保持着,当指定的时间到了又会自动恢复运行状态。在调用sleep()方法的过程中,线程不会释放对象锁
3.wait()方法会导致线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
注意是准备获取对象锁进入运行状态,而不是立即获得
4.wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
5.sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

suspend()方法用来使线程挂起,要通过resume()方法使其重新启动

3.正确的结论:
1.JDK1.7以前ConcurrentHashMap 使用segment来分段和管理锁,segment继承自ReentrantLock,因此ConcurrentHashMap使用ReentrantLock来保证线程安全,而非synchronized关键字。JDK1.8 的 ConcurrentHashMap 采用CAS+Synchronized保证线程安全。
2.Arrays.asList() 返回 java.util.Arrays.ArrayList 对象,这里的 ArrayList 是 Arrays 私有的内部类。

4.线程类
run()方法是用来定义这个线程在启动的时候需要做什么,即定义执行体。直接调用线程的run()方法只会执行一遍函数体,而不会开辟线程,只将其看做该线程对象的一般方法。
start()方法是启动线程,是将线程纳入线程调度,而在启动线程后执行的则是run()中定义的方法
创建一个线程需要覆盖Thread类的run方法,然后调用Thread类的start()方法启动

调用start()后,线程会被放到等待队列,等待CPU调度,并不一定要马上开始执行,只是将这个线程置于可动行状态。然后通过JVM,线程Thread会调用run()方法,执行本线程的线程体。
1.start()方法来启动线程,真正实现了多线程运行。这时无需等待run方法体代码执行完毕,可以直接继续执行下面的代码;
2.run()方法当作普通方法的方式调用。程序还是要顺序执行,要等待run方法体执行完毕后,才可继续执行下面的代码, 这样就没有达到写线程的目的。

并发

知识点:

1.各个锁用到的CPU指令:
volatile:
synchronized:
CAS:

2.各种术语的概念:
happens-before:
as-if-serial:
fast-fail:
顺序一致性:
CAS:
AQS:
fork-join:
future-task:

笔试错题:

1.共享内存不提供同步机制。所以我们通常需要用其他的机制来同步对共享内存的访问,例如前面说到的信号量。我们可以用shmget函数来创建共享内存。

2.可重入函数,被认为是可以中断的函数,其中的自动变量被视为函数内局部作用域变量,不需要互斥量;而其中的全局变量需要互斥量保护。并且可重入函数不可以调用不可重入函数,废话,调用了就不叫可重入函数了。

3.接2,多线程保护的是全局变量和静态变量,函数里的局部变量并不用进行保护。

4.并发,用于单CPU系统,让CPU轮询切换进程,解决并发的同步问题:采用(封)锁、时间戳、乐观控制法的方式;并行,用于多CPU系统,多CPU同时执行任务。
明显轮询比抢占简单,因为不需要记录连接状态。

5.进程:子进程获得父进程的数据空间,堆、栈的复制品。所以多进程可以在不同的核上运行。 线程:线程可以和同进程的其他线程共享数据,并且拥有自己的栈空间和程序计数器。多线程并不能跨机器运行。

6.无锁化编程的方法:
针对计数器可以用原子加;
只有一个生产者和一个消费者,那么就可以做到免锁访问环形缓冲区(Ring Buffer);
RCU(Read-Copy-Update),新旧副本切换机制,对于旧副本可以采用延迟释放的做法;
CAS(Compare-and-Swap),如无锁栈,无锁队列等待;

错题与相关知识点:

1.进程与线程的区别与联系?线程怎么同步?进程怎么通信?

进程间通信:管道、System V消息队列、Posix消息队列、远程过程调用。共享内存、信号。 进程间资源是独立的,讲通讯:管道,共享内存。

线程同步方法:临界区、互斥量、信号量 线程间资源是共享的,讲安全:信号量,锁,原子操作。

2.简单介绍一下进程的切换过程?

1.JDK提供的用于并发编程的同步器有:最常用的同步器是CountDownLatch和Semaphore,不常用的是Barrier 和Exchanger。
A. semaphore:信号量。用于表示共享资源数量。用acquire()获取资源,用release()释放资源。
B. CyclicBarrier 线程到达屏障后等待,当一组线程都到达屏障后才一起恢复执行
C. CountDownLatch 初始时给定一个值,每次调用countDown值减1,当值为0时阻塞的线程恢复执行

2.java用监视器(即锁)机制实现了进程之间的同步执行

3.ThreadLocal类 用锁的地方基本都希望读多写少

ThreadLocal类用于创建一个线程本地变量
在Thread中有一个成员变量ThreadLocals,该变量的类型是ThreadLocalMap,也就是一个Map,它的键是threadLocal,值为就是变量的副本。通过ThreadLocal的get()方法可以获取该线程变量的本地副本,在get方法之前要先set,否则就要重写initialValue()方法。

ThreadLocal的使用场景:
数据库连接:在多线程中,如果使用懒汉式的单例模式创建Connection对象,由于该对象是共享的,那么必须要使用同步方法保证线程安全,这样当一个线程在连接数据库时,那么另外一个线程只能等待。这样就造成性能降低。如果改为哪里要连接数据库就来进行连接,那么就会频繁的对数据库进行连接,性能还是不高。这时使用ThreadLocal就可以既可以保证线程安全又可以让性能不会太低。但是ThreadLocal的缺点时占用了较多的空间。

ThreadLocal如何实现:

1.如何实现一个生产者与消费者模型?(锁、信号量、线程通信、阻塞队列等)?

2.如何理解线程的同步与异步、阻塞与非阻塞?

3.线程池处理任务的流程是怎样的?

4.Synchronized 和 ReentrantLock 有什么不同?各适合什么场景?

5.读写锁适用于什么场景?ReentrantReadWriteLock是如何实现的?

6.线程之间如何通信?

7.死锁的产生条件?如何分析是否有线程死锁?

8.如何尽可能提高多线程并发性能?

集合

知识点:

1.vector是线程安全的ArrayList,在内存中占用连续的空间。初始时有一个初始大小,当数据条数大于这个初始大小后会重写分配一个更大的连续空间。如果Vector定义为保存Object则可以存放任意类型。

1.常考问题

try-catch

知识点:

1.finally中的语句一定会执行。
2.是catch捕获到异常后程序结束。
3.注意throws是写在方法上,申明要抛出的异常。throw是抛出异常。
4.finally前有return,会先执行return语句,并保存下来,再执行finally块,最后return。
5.finally前有return、finally块中也有return,先执行前面的return,保存下来,再执行finally的return,覆盖之前的结果,并返回。
6.try必须,catch和finally不是必须,但是不能同时省略。

error类异常主要是运行时逻辑错误导致,一个正确程序中是不应该出现error的。当出现error一般jvm会终止。error类体系描述了Java运行系统中的内部错误以及资源耗尽的情形,Error不需要捕捉
exception表示可恢复异常,包括检查异常和运行时异常。 非RuntimeException(可分3类)检查异常是最常见异常比如 io异常sql异常,都发生在编译阶段。这类通过try、catch捕捉
而RuntimeException运行时异常,编译器没有强制对其进行捕捉和处理。一般都会把异常向上抛出,直到遇到处理代码位置,若没有处理块就会抛到最上层,多线程用thread。run()抛出,单线程用main()抛出。常见的运行异常包括 空指针异常 类型转换异常 数组月结异常 数组存储异常 缓冲区溢出异常 算术异常等。故零除时并不需要抛出异常,

若 catch 中的参数类型有父类子类关系,此时应该将父类放在后面,子类放在前面。如果将父类放在前面的话,异常将被父类完全捕获,子类永远不能捕获异常

错题及相关知识点:

1.简单描述一下java的异常机制?

JVM

1.jvm中垃圾回收分为scanvenge gc和full GC,其中full GC触发的条件可能有:老年代满、持久代满、System.gc()。
Minor GC:
新生代:(1)所有对象创建在新生代的Eden区,当Eden区满后触发新生代的Minor GC,将Eden区和非空闲Survivor区存活的对象复制到另外一个空闲的Survivor区中。(2)保证一个Survivor区是空的,新生代Minor GC就是在两个Survivor区之间相互复制存活对象,直到Survivor区满为止。
老年代:当Survivor区也满了之后就通过Minor GC将对象复制到老年代。老年代也满了的话,就将触发Full GC,针对整个堆(包括新生代、老年代、持久代)进行垃圾回收。

2.如果经常发生full GC,如何定位,如何解决

full gc频繁说明old区很快满了。

如果是一次fullgc后,剩余对象不多。那么说明你eden区设置太小,导致短生命周期的对象进入了old区。
如果一次fullgc后,old区回收率不大,那么说明old区太小。

题主用的是Oracle JDK7,既然题主说这个现象“经常性出现”,那么要知道是上述三种情况的哪一种,最好的办法是用:
jstat -gccause

2.有关的内存分配:1.数组的引用存在栈内存中,而数组对象保存在堆里面。 2.所有的对象类都是在堆内存中,基本数据类型在栈内存中。 3.如果变量被static修饰,那么该变量属于类,该类的所有对象操作的都是同一个变量。类变量存储在方法区,不属于每个实例的私有。

3.Runtime.gc()调用之后是否立即清理等等gc问题?

java.lang.System.gc()只是java.lang.Runtime.getRuntime().gc()的简写,两者的行为没有任何不同。唯一要能说有什么不同那就是在字节码层面上调用前者比调用后者短一点点,前者是1条字节码而后者是2条System.gc():invokestatic java/lang/System.gc()V
Runtime.getRuntime().gc():invokestatic java/lang/Runtime.getRuntime()Ljava/lang/Runtime;
invokevirtual java/lang/Runtime.gc()V
实际运行起来性能几乎一样。不过如果对字节码大小非常非常敏感的话建议用System.gc()。从通常的代码习惯说也是System.gc()用得多些。---------------------------------------------------------------要说别的触发GC的方式,倒确实还有别的。一个是进程内外皆可用的、基于JMX的方式,java.lang.management.MemoryMXBean.gc()。例如说JConsole里的“GC”按钮就是用这个方式实现的,参考这帖:http://hllvm.group.iteye.com/group/topic/35871另一个是Oracle/Sun系的JVM所支持的attach API,从Java 6开始可以用。例如说通过jmap -histo:live这样会触发一次full GC,这个就是基于attach API来实现的。

4.数组的引用存在栈内存中,而数组对象保存在堆里面。

  1. 内存抖动

内存抖动是由于短时间内有大量对象进出新生区导致的,它伴随着频繁的GC。 gc会大量占用ui线程和cpu资源,会导致app整体卡顿。获取频繁更换页面

IO

1.System.in 和 System.out 是java中的标准输入输出流,一般情况下代表从控制台输入获取数据,和输出到控制台.划分输入/输出流时是从程序运行所在的内存的角度来考虑的.,数据从内存到硬盘,通常称为输出流。
java的输入流主要是InputStream和Reader作为基类,而输出流则是主要由outputStream和Writer作为基类。它们都是一些抽象基类,无法直接创建实例。

网络

1.管道只能单工、半双工,不能全双工。

Spring

1.Servlet接口的方法:init,destory方法 ; HttpServlet中的方法:doGet和doPost(do系列)、encodeURL ;RequestDispatcher的方法 : forward ; HttpServletResponse中的方法: sendRedirect方法(重定向); HttpServletRequest接口

2.对象的设计应使类和构件之间的耦合最小 ;

3.对ORM框架,Spring并没有自己实现,只对JDBC和其他ORM框架进行了封装。

4.spring的PROPAGATION_REQUIRES_NEW事务:内部事务回滚了,外部事务仍然可以提交。

5.spring的IOC容器能够帮我们自动new对象,对象交给spring管之后我们不用自己手动去new对象了,也就是控制权的转让。spring使用BeanFactory来实例化、配置和管理对象,但是它只是一个接口,里面有一个getBean()方法。我们一般都不直接用BeanFactory,而是用它的实现类 ApplicationContext ,这个类会自动解析我们配置的applicationContext.xml
Spring的特色之一,简单而强大的事务管理功能,包括编程式事务和声明式事务。编程式事务:代码中注解实现的事务;声明式事务:配置文件中配置的事务。

6.spring的依赖注入:先看有没有值(setter)注入,没有的时候按构造注入,一旦有值注入则构造注入失效。

7.spring DAO, Spring提供了一套抽象DAO类供你扩展。这些抽象类提供了一些方法,用来简化代码开发。 IoC 容器的使用,提供了 DAO 组件与业务逻辑组件之间的解耦。: Spring的声明式事务管理力度是方法级。Struts2是类级别的。

8.Spring mvc的入口是servlet,而struts2是filter。两者更多区别more

9.在Spring中,Bean的scope默认是singleton的,也就是“单例”。

10.request.getAttribute()方法返回request范围内存在的对象,而request.getParameter()方法是获取http提交过来的数据。getAttribute是返回对象,getParameter返回字符串。

场景题

1.公司有很多部门,每个部门负责不同的业务,如短信推送业务、验证码业务、人脸识别业务等等。现在要求设计一个公共管理平台,将这些业务整合到一起,这样外界可以通过这个平台调用公司的各项业务,要求考虑安全方面等。【我是以dubbo微服务,暴露在zookeeper,然后zookeeper统一入口,把消费者生产者分离这个角度答的,因为最近项目刚好用到,不知道对不对】分布式的架构,做的几个单独服务分成不同系统,然后系统前后端再分离,统一使用dubbo服务,注册在zookeeper管理中心等等,

2.假如你这个表有8000万条数据,单张表还能存的下嘛?对于8000万数据的表应该怎么处理?

3.有这样一个场景,不知道你遇到过没有?就是有一个Java应用,它依赖了两个库A和B,A和B又同时依赖了C库,但是A库和B库依赖的C库的版本不一样,如何解决不兼容的问题。

12、10万个数,输出从小到大?
先划分成多个小文件,送进内存排序,然后再采用多路归并排序。
13、有十万个单词,找出重复次数最高十个?
7、给每个组分配不同的IP段,怎么设计一种结构使的快速得知IP是哪个组的?
8、10亿个数,找出最大的10个。
建议一个大小为10的小根堆。