天天看点

最全Java知识点

HashCode被设计用来提高性能。equals()方法与hashCode()方法的区别在于:

1,如果两个对象相等(equal),那么他们一定有相同的哈希值。

2,如果两个对象的哈希值相同,但他们未必相等(equal)。

设计模式:

代理模式:

定义:为其他对象提供一种代理,以控制对这个对象的访问

     代理对象起到中介的作用,可去掉功能服务或增加额外的服务

     火车票代售点就是火车站售票处的代理

常见的代理模式:

远程代理:  为不同地理的对象提供局域网代表对象,

  例:客户端&服务器

虚拟代理: 根据需要将资源消耗很大的对象进行延迟,真正需要的时候进行创建

  例:浏览帖子,正文优先加载,图片延迟加载

保护代理: 对权限进行控制

  例:只有登录才能发帖等等

   智能引用代理:  提供对目标对象额外服务

  例: 火车票代售处提供一些额外服务

以只能引用代理为例:

静态代理:代理和被代理对象在代理之前是确定的。他们都实现相同的接口或继承相同的抽象类

------------------------------------------------------------------------------------------------------------

下列哪种说法是正确的( )

  A 实例方法可直接调用超类的实例方法

  B 实例方法可直接调用超类的类方法

  C 实例方法可直接调用其他类的实例方法

  D 实例方法可直接调用本类的类方法

  选d,类方法就是静态方法。其它的就是实例方法

  实例方法可以对当前对象的实例变量进行操作,也可以对类变量进行操作,

  但类方法不能访问实例变量。实例方法必须由实例对象来调用,而类方法除了可由实例对象调用外,还可以由类名直接调用。

  另外,在类方法中不能使用 this 或 super。 关于类方法的使用,有如下一些限制:

  1 在类方法中不能引用对象变量。

  2 在类方法中不能使用super、this关键字。

  3 类方法不能调用类中的对象方法。与类方法相比,实例方法几乎没有什么限制:

  1 实例方法可以引用对象变量(这是显然的),也可以引用类变量。

  2 实例方法中可以使用super、this关键字。

  3 实例方法中可以调用类方法。

------------------------------------------------------------------------------------------------------------

关于C++/JAVA类中static 成员和对象成员的说法正确的是?

 A static 成员变量在对象构造时生成

 B static 成员函数在对象成员函数中无法调用

 C 虚成员函数不可能是static成员函数

 D static 成员函数不能访问static成员变量

 static为成员变量或函数,在类初始化是加载完成,可以被成员函数调用或访问

 在java语言中虚函数指代的就是抽象方法,抽象方法中不能用private,static,synchronized,native等修饰词修饰。

------------------------------------------------------------------------------------------------------------

有如下一段代码,请选择其运行结果()

 public class StringDemo{

    private static final String MESSAGE="taobao";

    public static void main(String [] args) {

       String a ="tao"+"bao";

       String b="tao";

       String c="bao";

       System.out.println(a==MESSAGE);

       System.out.println((b+c)==MESSAGE);

    }

  }

 Java对String的相加是通过StringBuffer实现的,先构造一个StringBuffer里面存放”tao”,

 然后调用append()方法追加”bao”,然后将值为”taobao”的StringBuffer转化成String对象。

 StringBuffer对象在堆内存中,那转换成的String对象理所应当的也是在堆内存中。

 MESSAGE成员变量及其指向的字符串常量肯定都是在栈内存里的

 对于字符串常量的相加,在编译时直接将字符串合并,而不是等到运行时再合并。也就是说

 String a = "tao" + "bao" 和String a =  "taobao"编译出的字节码是一样的。

 所以等到运行时,根据上面说的栈内存是数据共享原则,a和MESSAGE指向的是同一个字符串。

------------------------------------------------------------------------------------------------------------

接口和抽象类:

相同点:都不能被实例化,位于继承树的顶端,都包含抽象方法

不同点:1、设计目的:

接口:

     体现的一种规范,类似与整个系统的总纲,

               制订了系统各模块应该遵循的标准,因此接口不应该经常改变,一旦改变对整个系统是辐射性的。

抽象类:

                      作为多个子类的共同父类,体现的是一种模板式设计,可以当作系统实现过程中的中间产品,已经实现了系统部分功能。

        2、使用不同

    (1)接口只能包含抽象方法,抽象类可以包含普通方法。

    (2)接口里不能定义静态方法,抽象类可以。

    (3)接口只能定义静态常量属性,不能定义普通属性,抽象类可以。

    (4)接口不包含构造器,抽象类可以(不是用于创建对象而是让子类完成初始化)。

    (5)接口里不能包含初始化块,抽象类完全可以。

    (6)接口多继承,抽象类单继承(只能有一个直接父类)。

总结:

   接口所有方法全是抽象方法只能public abstract修饰(默认public abstract修饰),属性默认public static final修饰。

抽象类除了包含抽象方法外与普通类无区别。 

------------------------------------------------------------------------------------------------------------

关于volatile关键字,下列描述

A 用volatile修饰的变量,每次更新对其他线程都是立即可见的   //正确

B 对volatile变量的操作是原子性的   //错误

C 对volatile变量的操作不会造成阻塞   //正确

D 不依赖其他锁机制,多线程环境下的计数器可用volatile实现     //错误

------------------------------------------------------------------------------------------------------------

两个最基本的java回收算法:

   复制算法和标记清理算法

                复制算法:两个区域A和B,初始对象在A,继续存活的对象被转移到B。此为新生代最常用的算法

                标记清理:一块区域,标记要回收的对象,然后回收,一定会出现碎片,那么引出

                标记-整理算法:多了碎片整理,整理出更大的内存放更大的对象

   两个概念:新生代和年老代

                新生代:初始对象,生命周期短的

                永久代:长时间存在的对象

   整个java的垃圾回收是新生代和年老代的协作,这种叫做分代回收。

   P.S: Serial New收集器是针对新生代的收集器,采用的是复制算法

         Parallel New(并行)收集器,新生代采用复制算法,老年代采用标记整理

         Parallel  Scavenge(并行)收集器,针对新生代,采用复制收集算法

         Serial Old(串行)收集器,新生代采用复制,老年代采用标记清理

         Parallel   Old(并行)收集器,针对老年代,标记整理

         CMS收集器,基于标记清理

         G1收集器:整体上是基于标记清理,局部采用复制

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

------------------------------------------------------------------------------------------------------------

Java虚拟机功能:

 1 通过 ClassLoader 寻找和装载 class 文件

 2 解释字节码成为指令并执行,提供 class 文件的运行环境

 3 进行运行期间垃圾回收

 4 提供与硬件交互的平台

------------------------------------------------------------------------------------------------------------

关于ThreadLocal以下说法正确的是?

A ThreadLocal继承自Thread         //错误,ThreadLocal继承Object,相当于没继承任何特殊的。

B ThreadLocal实现了Runnable接口         //错误,ThreadLocal没有实现任何接口

C ThreadLocal重要作用在于多线程间的数据共享       //错误

D ThreadLocal是采用哈希表的方式来为每个线程都提供一个变量的副本              //正确

E ThreadLocal保证各个线程间数据安全,每个线程的数据不会被另外线程访问和破坏   //正确

   线程的角度看,每个线程都保持一个对其线程局部变量副本的隐式引用,只要线程是活动的并且 ThreadLocal 实例是可访问的;

在线程消失之后,其线程局部实例的所有副本都会被垃圾回收

------------------------------------------------------------------------------------------------------------

以下JAVA程序的输出是什么()

public class HelloSogou{

     public static synchronized void main(String[] a){

         Thread t=new Thread(){

             public void run(){Sogou();}

     };

     t.run();

     System.out.print("Hello");

     }

     static synchronized void Sogou(){

     System.out.print("Sogou");

    }

}

A HelloSogou     B SogouHello        C Hello       D 结果不确定

------------------------------------------------------------------------------------------------------------

如果是t.start(),(静态同步函数的锁是该类的字节码文件.class main函数和Sogou方法都是static的,所以持有相同锁

HelloSogou.class那么,在main线程(main 是一个线程也是一个进程 )中又开了一个线程,调用Sogou方法,锁会冲突。 选D

但是,t.run()只是普通方法,顺序执行,选B

-----------------------------------------------------------------------------------------------------------

ServerSocket (int port)

创建一个serversocket 绑定在特定的端口

Socket(InetAddress address, int port)

创建一个socket流,连接到特定的端口和ip地址

------------------------------------------------------------------------------------------------------------

一般关系数据模型和对象数据模型之间有以下对应关系:表对应类,记录对应对象,表的字段对应类的属性。

------------------------------------------------------------------------------------------------------

线程通过调用对象的synchronized方法可获得对象的互斥锁定;

线程调度算法是平台独立的:

线程调度分为协同式调度和抢占式调度,Java使用的是抢占式调度,也就是每个线程将由操作系统来分配执行时间,

线程的切换不由线程本身来决定(协同式调度)。这就是平台独立的原因。

------------------------------------------------------------------------------------------------------------

优化Hibernate所鼓励的7大措施:

1.尽量使用many-to-one,避免使用单项one-to-many

2.灵活使用单向one-to-many

3.不用一对一,使用多对一代替一对一

4.配置对象缓存,不使用集合缓存

5.一对多使用Bag 多对一使用Set

6.继承使用显示多态 HQL:from object polymorphism="exlicit" 避免查处所有对象

7.消除大表,使用二级缓存

------------------------------------------------------------------------------------------------------------

class Car extends Vehicle

{

    public static void main (String[] args)

    {

        new  Car(). run();

    }

    private final void run()

    {

        System. out. println ("Car");

    }

}

class Vehicle

{

    private final void run()

    {

        System. out. println("Vehicle");

    }

}

首先final声明的方法是不能被覆盖的,但是这里并不错误,因为方法是private的,

也就是子类没有继承父类的run方法,因此子类的run方法跟父类的run方法无关,并不是覆盖。

new Car().run()也是调用子类的run方法。输出Car。

************************************************************************************************************v

************************************************************************************************************

public class Test2

{

    public void add(Byte b){

        b = b++;

    }

    public void test(){

        Byte a = 127;

        Byte b = 127;

        add(++a);

        System.out.print(a + " ");

        add(b);

        System.out.print(b + "");

    }

}

public void add(Byte b){ b=b++; } 这里涉及java的自动装包/自动拆包(AutoBoxing/UnBoxing) 

Byte的首字母为大写,是类,看似是引用传递,但是在add函数内实现++操作,会自动拆包成byte值传递类型,

所以add函数还是不能实现自增功能。也就是说add函数只是个摆设,没有任何作用。 Byte类型值大小为-128~127之间。

add(++a);这里++a会越界,a的值变为-128 add(b); 前面说了,add不起任何作用,b还是127

************************************************************************************************************

************************************************************************************************************

class C {

    C() {

        System.out.print("C");

    }

}

class A {

    C c = new C();

    A() {

        this("A");

        System.out.print("A");

    }

    A(String s){

        System.out.print(s);

    }

}

class Test extends A{

    Test(){

        super("B");

        System.out.print("B");

    }

    public static void main(String[] args) {

        new Test();

    }

}

//解答1:

初始化过程是这样的: 父类B静态代码块->子类A静态代码块->父类B非静态代码块->父类B构造函数->子类A非静态代码块->子类A构造函数

1.首先,初始化父类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化; 

2.然后,初始化子类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化; 

3.其次,初始化父类的普通成员变量和代码块,在执行父类的构造方法;

4.最后,初始化子类的普通成员变量和代码块,在执行子类的构造方法; 

(1)初始化父类的普通成员变量和代码块,执行 C c = new C(); 输出C 

(2)super("B"); 表示调用父类的构造方法,不调用父类的无参构造函数,输出B 

(3) System.out.print("B"); 

 所以输出CBB

//解答2:

首先new了一个子类对象,那么就要调用构造方法来初始化该子类对象,但是该类继承自A,所以要先调用父类的构造方法,

这里通过super("B")显示的调用了父类的带参构造。

执行父类的带参构造前要先对父类中的对象进行初始化,对父类中的c成员进行初始化,调用了C类的无参构造,所以调用顺序为:

先调用C类的无参构造

再调用A类的带参构造

最后调用调用子类的构造

------------------------------------------------------------------------------------------------------------

假设有以下代码String s = "hello":String t = “hello”;char c [ ] = {'h','e','l','l','o'};下列选项中返回false的语句是?

A s.equals (t);

B t.equals (c);

C s==t;

D t.equals (new String ("hello"));

Sting 类保存字符串只是保存所有单单的字符串;

而 char[] 字符数组 会在最后自动加上'\n';

所以B:t.equals(c)会返回fasle;

所以 答案B

------------------------------------------------------------------------------------------------------------

根据下面的代码,

String s = null;

会抛出NullPointerException异常的有:

  A if( (s!=null) & (s.length()>0) )  B if( (s!=null) && (s.length()>0) )

  C if( (s==null) | (s.length()==0))  D if( (s==null) || (s.length()==0) )

String s=null;没有给s开辟任何空间,当执行length()方法时候,

因为没有具体指向的内存空间,所以报出NullPointerException没有指向的错误。

A &是与,位运算,两个都得执行,执行到s.length()自然就报错了。

B s!=null  结果为false 整体就为false ,&& 后面就不会执行。下面的同理。 AC

------------------------------------------------------------------------------------------------------------

************************************************************************************************************

************************************************************************************************************

HashMap和Hashtable两个类都实现了Map接口,二者保存K-V对(key-value对)

HashTable不允许null值(key和value都不可以),HashMap允许null值(key和value都可以)。

Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap就必须为之提供外同步

迭代 HashMap 采用快速失败机制,而 HashTable 不是,因为 HashTable是线程安全的

HashMap把Hashtable的contains方法去掉了,改成 containsvalue 和 containsKey。因为contains方法容易让人引起误解

HashTable使用Enumeration,HashMap使用Iterator

************************************************************************************************************

************************************************************************************************************

------------------------------------------------------------------------------------------------------------

例化线程: 1、如果是扩展java.lang.Thread类的线程,则直接new即可。

           2、如果是实现了java.lang.Runnable接口的类,则用Thread的构造方法:

public class MyRunnable implements Runnable{ 

     public void run()             { 

        (new Thread(new MyRunnable()).start()

     } 

 }

------------------------------------------------------------------------------------------------------------

<<表示左移位

>>表示带符号右移位

>>>表示无符号右移

但是没有<<<运算符

------------------------------------------------------------------------------------------------------------

  CopyOnWriteArrayList适用于读多写少的并发场景

  ReadWriteLock即为读写锁,要求写与写之间互斥,读与写之间互斥,读与读之间可以并发执行。在读多写少的情况下可以提高效率

  ConcurrentHashMap是同步的HashMap,读写都加锁

  volatile只保证多线程操作的可见性,不保证原子性

------------------------------------------------------------------------------------------------------------

String str = new String("abc"),"abc"在内存中是怎么分配的?

A 堆

B 栈

C 字符串常量区

D 寄存器

当你new String("abc")时,其实会先在字符串常量区生成一个abc的对象,然后new String()时会在堆中分配空间,

然后此时会把字符串常量区中abc复制一个给堆中的String,故abc应该在堆中和字符串常量

------------------------------------------------------------------------------------------------------------

byte b1=1,b2=2,b3,b6,b8;

final byte b4=4,b5=6,b7;

b3=(b1+b2);  

b6=b4+b5;    

b8=(b1+b4);  

b7=(b2+b5);  

上面代码片段中,存在编辑错误的语句是?

本题答案应为:B、C、D

Java表达式转型规则由低到高转换:

1、所有的byte,short,char型的值将被提升为int型;

2、如果有一个操作数是long型,计算结果是long型;

3、如果有一个操作数是float型,计算结果是float型;

4、如果有一个操作数是double型,计算结果是double型;

5、被fianl修饰的变量不会自动改变类型,当2个final修饰相操作时,结果会根据左边变量的类型而转化。

语句1错误:b3=(b1+b2);  自动转为int,所以正确写法为b3=(byte)(b1+b2);或者将b3定义为int;

语句2正确:b6=b4+b5;    b4、b5为final类型,不会自动提升,所以和的类型视左边变量类型而定,即b6可以是任意数值类型;

语句3错误:b8=(b1+b4);  虽然b4不会自动提升,但b1仍会自动提升,所以结果需要强转,b8=(byte)(b1+b4);

语句4错误:b7=(b2+b5);  同上。同时注意b7是final修饰,即只可赋值一次,便不可再改变。

------------------------------------------------------------------------------------------------------------

Java类Demo中存在方法func0、func1、func2、func3和func4,请问该方法中,哪些是不合法的定义?( )

public class Demo{

  float func0() byte,short,char-> int -> long -> float -> double

  { 小转大不用强转,大转小需要强转

    byte i=1; func1  没有返回值;func4  大转小需要强转

    return i;

  }

  float func1()

  {

    int i=1;

    return;

  }

  float func2()

  {

    short i=2;

    return i;

  }

  float func3()

  {

    long i=3;

    return i;

  }

  float func4()

  {

    double i=4;

    return i;

  }

}

------------------------------------------------------------------------------------------------------------

java中除了基本数据类型都是引用数据类型

java中的基本数据类型如下:

byte   short  int   long   float   double   char  boolean

除此之外都是引用类型

------------------------------------------------------------------------------------------------------------

可用来实现线程间通知和唤醒:

    Object.wait/notify/notifyAll

    Condition.await/signal/signalAll

------------------------------------------------------------------------------------------------------------

Statement是sql语句的载体

Statement是标准的Statement类,通过字符串对sql语句进行拼接,但是它存在sql注入的危险

PreparedStatement对sql语句进行了预编译,可以防止SQL注入

CallableStatement用来调用存储过程的

BatchedStatement用于批量操作数据库,BatchedStatement不是标准的Statement类

------------------------------------------------------------------------------------------------------------

面向对象的五大基本原则:

   单一职责原则(SRP)

   开放封闭原则(OCP) 

   里氏替换原则(LSP) 

   依赖倒置原则(DIP) 

   接口隔离原则(ISP)

-----------------------------------------------------------------------------------------------------------

下面有关java实例变量,局部变量,类变量和final变量的说法,错误的是?

A 实例变量指的是类中定义的变量,即成员变量,如果没有初始化,会有默认值    // 正确

B 局部变量指的是在方法中定义的变量,如果没有初始化,会有默认值            //********局部变量必须有初始值******

C 类变量指的是用static修饰的属性       //正确

D final变量指的是用final修饰的变量       //正确

------------------------------------------------------------------------------------------------------------

构造函数不可以用private修饰   //错误,单例模式中,构造器私有化

构造函数必须与类名相同        //正确

构造方法不能被子类继承,所以用final修饰没有意义。

构造方法用于创建一个新的对象,不能作为类的静态方法,所以用static修饰没有意义。

此外,Java语言不支持native或synchronized的构造方法

-----------------------------------------------------------------------------------------------------------

Java默认使用Unioncode编码,即不论什么语言都是一个字符占两个字节

Java的class文件编码为UTF-8,而虚拟机JVM编码为UTF-16

UTF-8编码下,一个中文占3个字节,一个英文占1个字节

Java中的char默认采用Unicode编码,所以Java中char占2个字节

1(byte)字节=8(bit)位

------------------------------------------------------------------------------------------------------------

floor:   求小于参数的最大整数。返回double类型-----n. 地板,地面

         例如:Math.floor(-4.2) = -5.0

ceil:   求大于参数的最小整数。返回double类型-----vt. 装天花板;

         例如:Math.ceil(5.6) = 6.0

round:  对小数进行四舍五入后的结果。返回int类型

         例如:Math.round(-4.6) = -5

----------------------------------------------------------------------------------------------------------

Integer i = 42;

Long l = 42l;

Double d = 42.0;   下面为true的是?

A i == l         B i == d      C l == d

D i.equals(d)        E d.equals(l)        F i.equals(l)      G l.equals(42L)

ABC3 个选项很明显,不同类型引用的 == 比较,会出现编译错误,不能比较。

DEF 调用 equals 方法,因为此方法先是比较类型,而 i , d , l 是不同的类型,所以返回假。

选项 G ,会自动装箱,将 42L 装箱成 Long 类型,所以调用 equals 方法时,类型相同,且值也相同,因此返回真

------------------------------------------------------------------------------------------------------------

Java致力于检查程序在编译和运行时的错误

Java虚拟机实现了跨平台接口

类型检查帮助检查出许多开发早期出现的错误

Java自己操纵内存减少了内存出错的可能性

Java还实现了真数组,避免了覆盖数据的可能

注意,是避免数据覆盖的可能,而不是数据覆盖类型 

------------------------------------------------------------------------------------------------------------

java不允许单独的方法,过程或函数存在,需要隶属于某一类中

java语言中的方法属于对象的成员,而不是类的成员。不过,其中静态方法属于类的成员

-----------------------------------------------------------------------------------------------------------

形式参数可被视为local variable

对于形式参数只能用final修饰符

形参的值在调用时根据调用者更改,实参则用自身的值更改形参的值(指针、引用皆在此列),也就是说真正被传递的是实参