2020-10-15

JAVA面试题 (1)

1.Java的跨平台性

因为Java程序编译之后的代码不是能被硬件系统直接运行的代码,而是一种“中间码”——字节码。然后不同的硬件平台上安装有不同的Java虚拟机(JVM),由JVM来把字节码再“翻译”成所对应的硬件平台能够执行的代码。因此对于Java编程者来说,不需要考虑硬件平台是什么。所以Java可以跨平台。

因为它有虚拟机(JVM),JAVA程序不是直接在电脑上运行的,是在虚拟机上进行的,每个系统平台都是有自己的虚拟机(JVM),所以JAVA语言能跨平台。

java代码不是直接运行在CPU上,而是运行在java虚机(简称JVM)上的。

java是先把java文件编译成二进制字节码的class文件,jvm就解释执行class文件。

就是因为java是运行在jvm上的,所以它的代码就能不经修改,就能在不同平台的jvm上运行(在UNIX用UNIX的jvm,在linux上用linux的jvm,在windows上用windows的jvm)

假如用windows移植到UNIX,只需把java文件是UNIX的jvm上编译成class文件,然后用jvm运行就可以了.

2.浅拷贝和深拷贝的区别

如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。

3.创建对象的方式

1.使用new创建对象
  使用new关键字创建对象应该是最常见的一种方式,但我们应该知道,使用new创建对象会增加耦合度。无论使用什么框架,都要减少new的使用以降低耦合度。

package yunche.test;


public class Hello
{
    public void sayWorld()
    {
        System.out.println("Hello world!");
    }

}
package yunche.test;


public class NewClass
{
    public static void main(String[] args)
    {
        Hello h = new Hello();
        h.sayWorld();
    }
}

2.使用反射的机制创建对象
使用Class类的newInstance方法
  Hello类的代码不变,NewClass类的代码如下:

package yunche.test;


public class NewClass
{
    public static void main(String[] args)
    {
        try
        {
           Class heroClass = Class.forName("yunche.test.Hello");
           Hello h =(Hello) heroClass.newInstance();
           h.sayWorld();
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (IllegalAccessException e)
        {
            e.printStackTrace();
        }
        catch (InstantiationException e)
        {
            e.printStackTrace();
        }

    }
}

使用Constructor类的newInstance方法

package yunche.test;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;


public class NewClass
{
    public static void main(String[] args)
    {
        try
        {
            //获取类对象
           Class heroClass = Class.forName("yunche.test.Hello");

           //获取构造器
           Constructor constructor = heroClass.getConstructor();
           Hello h =(Hello) constructor.newInstance();
           h.sayWorld();
        }
        catch (NoSuchMethodException e)
        {
            e.printStackTrace();
        }
        catch (InvocationTargetException e)
        {
            e.printStackTrace();
        }
        catch (IllegalAccessException e)
        {
            e.printStackTrace();
        }
        catch (InstantiationException e)
        {
            e.printStackTrace();
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }

    }
}

3.采用clone
  clone时,需要已经有一个分配了内存的源对象,创建新对象时,首先应该分配一个和源对象一样大的内存空间。

要调用clone方法需要实现Cloneable接口,由于clone方法是protected的,所以修改Hello类。

package yunche.test;


public class Hello implements Cloneable
{
    public void sayWorld()
    {
        System.out.println("Hello world!");

    }

    public static void main(String[] args)
    {
        Hello h1 = new Hello();
        try
        {
            Hello h2 = (Hello)h1.clone();
            h2.sayWorld();
        }
        catch (CloneNotSupportedException e)
        {
            e.printStackTrace();
        }
    }
}

4.采用序列化机制
  使用序列化时,要实现实现Serializable接口,将一个对象序列化到磁盘上,而采用反序列化可以将磁盘上的对象信息转化到内存中。

package yunche.test;

import java.io.*;


public class Serialize
{
    public static void main(String[] args)
    {
        Hello h = new Hello();

        //准备一个文件用于存储该对象的信息
        File f = new File("hello.obj");

        try(FileOutputStream fos = new FileOutputStream(f);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            FileInputStream fis = new FileInputStream(f);
            ObjectInputStream ois = new ObjectInputStream(fis)
            )
        {
            //序列化对象,写入到磁盘中
            oos.writeObject(h);
            //反序列化对象
            Hello newHello = (Hello)ois.readObject();

            //测试方法
            newHello.sayWorld();
        }
        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
    }
}

4.integer a = 127

Integer a = 127;

Integer b = 127;

Integer c = 128;

Integer d = 128;

a == b 与 c == d 的比较结果是什么?

a == b 的结果为true 而 c == d的结果为false;

为什么会出现结果?回去百度之后发现问题的根源所在,在解决这个问题之前,先说说常量池的概念,百度百科上有

我在复述一遍。

Java常量池
常量池在java中用于保存编译期已经确定的,它包括了关于类,方法,接口中的常量,也包括字符串常量。例如
String s = “Java” 这种声明的方式。产生的这种"常量"就会被放到常量池,常量池是JVM的一块特殊的内存空间。
使用Java常量池技术,是为了方便快捷地创建某些对象,当你需要一个对象时候,就去这个池子里面找,找不到就在 池子里面创建一个。但是必须注意 如果对象是用new 创建的。那么不管是什么对像,它是不会放到池子里的,而是向堆申请新的空间存储。
java中基本类型的包装类的大部分都实现了常量池技术,这些类是Byte,Short,Integer,Long,Character,Boolean,另外两种浮点数类型的包装类则没有实现。另外Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值小于等于127时才可使用对象池。超过了就要申请空间创建对象了
”==“ 我们知道比较的是引用的地址(其实java不要允许用户直接对内存进行操作的的)。

当我们使用Integer a = 127 的时候 实际上调用的是下面这个方法:

 public static Integer valueOf(int i) {
        assert IntegerCache.high >= 127;
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

如果 数在 -128到127之间 就返回池子中的对象。没有的话就创建
如果超过范围,看到没有return new Integer(i) 就是要在堆上重新申请一段了。

其实如果问题是这样的话

Integer a = new Integer(127);

Integer b = new Integer(127);

Integer c = 128;

Integer d = 128;

a == b 一定为false 因为 没有去找常量池,a,b都是在堆中申请了空间 返回的引用肯定不一样。因此为

5.MySQL中#和$的区别

符号将传入的数据都当做一个字符串,会对自动传入的数据加一个双引号;
$ 符号将传入的数据直接显示生成 SQL 中;
符号存在预编译的过程,,对问号赋值,防止 SQL 注入;
$ 符号是直译的方式,一般用在 order by ${列名}语句中;
能用#号就不要用 $ 符号。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值