Java 编程基础之易错题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kaikai_sk/article/details/82974546

Spring 七大模块

七大模块,如下:

  1. Spring Core: Core封装包是框架的最基础部分,提供IOC和依赖注入特性。这里的基础概念是BeanFactory,它提供对Factory模式的经典实现来消除对程序性单例模式的需要,并真正地允许你从程序逻辑中分离出依赖关系和配置。

2.Spring Context: 构建于Core封装包基础上的 Context封装包,提供了一种框架式的对象访问方法,有些象JNDI注册器。Context封装包的特性得自于Beans封装包,并添加了对国际化(I18N)的支持(例如资源绑定),事件传播,资源装载的方式和Context的透明创建,比如说通过Servlet容器。

3.Spring DAO: DAO (Data Access Object)提供了JDBC的抽象层,它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码。 并且,JDBC封装包还提供了一种比编程性更好的声明性事务管理方法,不仅仅是实现了特定接口,而且对所有的POJOs(plain old Java objects)都适用。

4.Spring ORM: ORM 封装包提供了常用的“对象/关系”映射APIs的集成层。 其中包括JPA、JDO、Hibernate 和 iBatis 。利用ORM封装包,可以混合使用所有Spring提供的特性进行“对象/关系”映射,如前边提到的简单声明性事务管理。

5.Spring AOP: Spring的 AOP 封装包提供了符合AOP Alliance规范的面向方面的编程实现,让你可以定义,例如方法拦截器(method-interceptors)和切点(pointcuts),从逻辑上讲,从而减弱代码的功能耦合,清晰的被分离开。而且,利用source-level的元数据功能,还可以将各种行为信息合并到你的代码中。

6.Spring Web: Spring中的 Web 包提供了基础的针对Web开发的集成特性,例如多方文件上传,利用Servlet listeners进行IOC容器初始化和针对Web的ApplicationContext。当与WebWork或Struts一起使用Spring时,这个包使Spring可与其他框架结合。

7.Spring Web MVC: Spring中的MVC封装包提供了Web应用的Model-View-Controller(MVC)实现。Spring的MVC框架并不是仅仅提供一种传统的实现,它提供了一种清晰的分离模型,在领域模型代码和Web Form之间。并且,还可以借助Spring框架的其他特性。

抽象类和接口

1、一个子类只能继承一个抽象类(虚类),但能实现多个接口;
2、一个抽象类可以有构造方法,接口没有构造方法;
3、一个抽象类中的方法不一定是抽象方法,即其中的方法可以有实现(有方法体),接口中的方法都是抽象方法,不能有方法体,只有声明;
4、一个抽象类可以是public、private、protected、default,
接口只有public;
5、一个抽象类中的方法可以是public、private、protected、default,
接口中的方法只能是public和default

floor和ceil

这里主要是有一点:

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,那么结果与参数相同,
如果是 -0.0,那么其结果是 -0.0

Object类中的方法

java object默认的基本方法中没有copy(),
含有如下方法:
getClass(), hashCode(), equals(), clone(), toString(), notify(), notifyAll(), wait(), finalize()

并发

CopyOnWriteArrayList适合使用在读操作远远大于写操作的场景里,比如缓存。
ReadWriteLock 当写操作时,其他线程无法读取或写入数据,而当读操作时,其它线程无法写入数据,但却可以读取数据 。适用于 读取远远大于写入的操作。
ConcurrentHashMap是一个线程安全的Hash Table,它的主要功能是提供了一组和HashTable功能相同但是线程安全的方法。ConcurrentHashMap可以做到读取数据不加锁,并且其内部的结构可以让其在进行写操作的时候能够将锁的粒度保持地尽量地小,不用对整个ConcurrentHashMap加锁。

保留字、关键字 和显式常量值

java中true ,false , null在java中不是关键字,也不是保留字,它们只是显式常量值,但是你在程序中不能使用它们作为标识符。

其中const和goto是java的保留字。java中所有的关键字都是小写的,还有要注意true,false,null, friendly,sizeof不是java的关键字,但是你不能把它们作为java标识符用。

垃圾收集器

两个最基本的java回收算法:复制算法和标记清理算法
复制算法:两个区域A和B,初始对象在A,继续存活的对象被转移到B。此为新生代最常用的算法
标记清理:一块区域,标记可达对象(可达性分析),然后回收不可达对象,会出现碎片,那么引出
标记-整理算法:多了碎片整理,整理出更大的内存放更大的对象
两个概念:新生代和年老代
新生代:初始对象,生命周期短的
永久代:长时间存在的对象
整个java的垃圾回收是新生代和年老代的协作,这种叫做分代回收。
P.S:Serial New收集器是针对新生代的收集器,采用的是复制算法
Parallel New(并行)收集器,新生代采用复制算法,老年代采用标记整理
Parallel Scavenge(并行)收集器,针对新生代,采用复制收集算法
Serial Old(串行)收集器,新生代采用复制,老年代采用标记整理
Parallel Old(并行)收集器,针对老年代,标记整理
CMS收集器,基于标记清理
G1收集器:整体上是基于标记 整理 ,局部采用复制

综上:新生代基本采用复制算法,老年代采用标记整理算法。cms采用标记清理。

String StringBuffer StringBuilder

效率:StringString(大姐,出生于JDK1.0时代) 不可变字符序列 <StringBuffer(二姐,出生于JDK1.0时代) 线程安全的可变字符序列 <StringBuilder(小妹,出生于JDK1.5时代) 非线程安全的可变字符序列 。Java中的String是一个类,而并非基本数据类型。string是值传入,不是引用传入。 StringBuffer和StringBuilder可以算是双胞胎了,这两者的方法没有很大区别。但在线程安全性方面,StringBuffer允许多线程进行字符操作。 这是因为在源代码中StringBuffer的很多方法都被关键字 synchronized 修饰了,而StringBuilder没有。 StringBuilder的效率比StringBuffer稍高,如果不考虑线程安全,StringBuilder应该是首选。另外,JVM运行程序主要的时间耗费是在创建对象和回收对象上。

StringBuffer:StringBuffer每次结果都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,再改变对象引用。

Collection 和 Map 接口

在这里插入图片描述

类继承

子类不可以继承父类的构造方法,只可以调用父类的构造方法。

线程启动

一 、定义线程: 1、扩展java.lang.Thread类。 2、实现java.lang.Runnable接口。
二、实例化线程: 1、如果是扩展java.lang.Thread类的线程,则直接new即可。
2、如果是实现了java.lang.Runnable接口的类,则用Thread的构造方法:
Thread(Runnable target)
Thread(Runnable target, String name)
Thread(ThreadGroup group, Runnable target)
Thread(ThreadGroup group, Runnable target, String name)
Thread(ThreadGroup group, Runnable target, String name, long stackSize)
三、启动线程: 在线程的Thread对象上调用start()方法,而不是run()或者别的方法。

Socket编程

线程停止和暂停执行

题目:什么操作会使得当前线程停止。

A:一个InterruptedException 异常被捕获

大家都知道的嘛 (一般通过interrupt方法 中断线程) 如果抓到一个线程 都会关紧catch里面 然后中断当前操作,A正确。

B:线程执行了wait()方法。

线程使用了wait方法,会强行打断当前操作,(暂停状态,不会中断线程) 进入阻塞(暂停)状态,然后需要notify方法或notifyAll方法才能进入就绪状态。 B 正确。

C:当前线程创建了一个新的线程。
新创建的线程不会抢占时间片,只有等当前线程把时间片用完,其他线程才有资格拿到时间片去执行。

D:一个高优先级别的线程就绪。

如C相同,你优先级别再高 也待等我现在弄完才会给你。(就像我们玩游戏,会员虽然有排队优先权,但是还是要等正在登陆的用户进去游戏之后才能抢到他原来那个位置,不能说我在过关卡的过程中你一脚把我踢开,然后霸占我的位置吧,我原来的那些数据咋办!!!)

E:线程在MediaTracker上执行了waitforID()调用。

这个应该大家也不太熟悉。这个类是awt里面的,我查API才知道。
然后他的功能是加载图像,直到完成之前,该方法一直等待!这个方法是必须要抛出A选项的InterruptedException 异常的 说明这玩意会让其他线程 wait他完成! 所以会暂停当前线程~~大概是这样吧哈哈哈! E选项我没选对! 这还是真的!。!

Vector 和 ArrayList

Vector & ArrayList 的主要区别
1) 同步性:Vector是线程安全的,也就是说是同步的 ,而ArrayList 是线程序不安全的,不是同步的 数2。
2)数据增长:当需要增长时,Vector默认增长为原来一倍 ,而ArrayList却是原来的50% ,这样,ArrayList就有利于节约内存空间。
如果涉及到堆栈,队列等操作,应该考虑用Vector,如果需要快速随机访问元素,应该使用ArrayList 。

扩展知识:

  1. Hashtable & HashMap
    Hashtable和HashMap它们的性能方面的比较类似 Vector和ArrayList,比如Hashtable的方法是同步的,而HashMap的不是。

  2. ArrayList & LinkedList

ArrayList的内部实现是基于内部数组Object[],所以从概念上讲,它更象数组,但LinkedList的内部实现是基于一组连接的记录,所以,它更象一个链表结构,所以,它们在性能上有很大的差别:
从上面的分析可知,在ArrayList的前面或中间插入数据时,你必须将其后的所有数据相应的后移,这样必然要花费较多时间,所以,当你的操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用ArrayList会提供比较好的性能; 而访问链表中的某个元素时,就必须从链表的一端开始沿着连接方向一个一个元素地去查找,直到找到所需的元素为止,所以,当你的操作是在一列数据的前面或中间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用LinkedList了。

final

/**
 * @author shankai
 * 
 * final作为对象成员存在时,必须初始化;但是,如果不初始化,也可以在类的构造函数中初始
 * 因为java允许将数据成员声明为final,却不赋初值。但是,blank finals必须在使用之前初始化,且必须在构造函数中初始化  
 */
class Foo 
{
	//	The blank final field i may not have been initialized
    final int i;
    int j;
    public void doSomething() {
        System.out.println(++j + i);
    }
}

Forward 和 redirect

1.从地址栏显示来说
forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址.
redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.

2.从数据共享来说
forward:转发页面和转发到的页面可以共享request里面的数据.
redirect:不能共享数据.

3.从运用地方来说
forward:一般用于用户登陆的时候,根据角色转发到相应的模块.
redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等.

4.从效率来说
forward:高.
redirect:低.

线程

class Solution 
{
	public static void main(String args[]) {
	    Thread t = new Thread() {
	        public void run() {
	            pong();
	        }
	    };
	    t.run();
	    System.out.print("ping");
	}
	static void pong() {
	    System.out.print("pong");
	}

}
pongping

这里需要注意Thread的start和run方法
用start方法才能真正启动线程,此时线程会处于就绪状态,一旦得到时间片,则会调用线程的run方法进入运行状态。
而run方法只是普通方法,如果直接调用run方法,程序只会按照顺序执行主线程这一个线程。

字符串和+

class Solution 
{
	public static void main(String[] args) 
	{
	    //先出现字符串,后面的内容自动强制转换为string进行拼接
		System.out.println("is "+ 100 + 5);
		System.out.println(100 + 5 +" is");
		System.out.println("is "+ (100 + 5));
	}
}
is 1005
105 is
is 105

类中的static关键字

1、abstract不能与final并列修饰同一个类 对的。
2、abstract类中不应该有private的成员 对的 :abstract类中可以有private 但是不应该有。
3、abstract方法必须在abstract类或接口中 对的 : 若类中方法有abstract修饰的,该类必须abstract修改。接口方法默认public abstract。
4、static方法中能处理非static的属性 错误 :在JVM中static方法在静态区,静态区无法调用非静态区属性。

class Solution 
{
	int sk;
	
	public static void main(String[] args) 
	{
		//		Cannot make a static reference to the non-static field sk
		sk = 1;
		System.out.println(new Two().x);
	}
}

HashMap和HashTable

HashTable中有contains方法

//以下是Hashtable的方法
public synchronized boolean contains(Object value)
public synchronized boolean containsKey(Object key)
public boolean containsValue(Object value)
 
//以下是HashMap中的方法,注意,没有contains方法,所以,D错误
public boolean containsKey(Object key)
public boolean containsValue(Object value)

HashTable中的null不可以作key。HashMap可以

//Hashtable的put方法有以下语句块,大伙看了都知道
// Make sure the value is not null
if (value == null) {
    throw new NullPointerException();
}
 
//那么,我们再来看下HashMap的put方法中,有如下语句
//调用某个方法直接把key为null,值为value的键值对插入进去。
if (key == null)
    return putForNullKey(value);

HashTable加了同步机制

public V put(K key, V value) //HashMap的put方法,没有同步
 
public synchronized V put(K key, V value) //Hashtable的put方法
//当然,Hashtable的其他方法,如get,size,remove等方法,
//都加了synchronized关键词同步操作
//HashMap的源码
public class HashMap<K,V>
    extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable
-----------------------------------
//Hashtable的源码
public class Hashtable<K,V>
    extends Dictionary<K,V>
    implements Map<K,V>, Cloneable, java.io.Serializable
----------------------------------
很明显,都实现了Map接口

嵌套类

为什么一个负责任的Java程序员想使用嵌套类?

A.为了让非常专门的类的代码与和它一起工作的类联系起来
B.为了支持产生特定事件的新的用户界面。
C.为了用Java知识给打动老板,到处使用嵌套类

AB

使用嵌套类,其中有几个令人信服的理由:

加强封装—考虑两个顶级类,A和B,如果B需要访问A的private成员,通过在A类隐藏B类,那么即使A的成员声明为private,那么B也可以访问它们。更多的是,B本身也可以隐藏于外部。

更可读性,可维护性的代码—在顶级类里嵌套小类,让代码更靠近使用的地方。

Byte的初始值

class Two
{
	Byte x;
}

class Solution 
{
	public static void main(String[] args) 
	{
		System.out.println(new Two().x);
	}

null

抽象类和final

在Java中下面Class的声明哪些是错误的?

A.
public abstract final class Test {
	abstract void method();
}

B.
public abstract class Test {
	abstract final void method();
}

C.
public abstract class Test {
	abstract void method() {
}
}

D.
public class Test {
	final void method() {

}
}

A、final修饰的类为终态类,不能被继承,而 抽象类是必须被继承的才有其意义的,因此,final是不能用来修饰抽象类的。
B、 final修饰的方法为终态方法,不能被重写。而继承抽象类,必须重写其方法。
C、抽象方法是仅声明,并不做实现的方法。

重写和重载

在Java中,以下关于方法重载和方法重写描述正确的是?
A方法重载和方法的重写实现的功能相同
B方法重载出现在父子关系中,方法重写是在同一类中
C方法重载的返回值类型必须一致,参数项必须不同
D方法重写的返回值类型必须相同或相容。
D

方法重写要注意的事项:
1.方法重写时, 方法名与形参列表必须一致。
2.方法重写时,子类的权限修饰符必须要大于或者等于父类的权限修饰符。
3.方法重写时,子类的返回值类型必须要小于或者 等于父类的返回值类型。
4.方法重写时, 子类抛出的异常类型要小于或者等于父类抛出的异常类型。
Exception(最坏)
RuntimeException(小坏)

方法的重载:在一个类中 存在两个或者两个 以上的同名函数,称作为方法重载。

方法重载的要求
1. 函数名要一致。
2. 形参列表不一致(形参的个数或形参 的类型不一致)
3. 与返回值类型无关。

访问权限

在类设计中,类的成员变量要求仅仅能够被同一package下的类访问,请问应该使用下列哪个修饰词(无修饰)

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/kaikai_sk/article/details/82974546