java基础

  • Post author:
  • Post category:java




1、请描述JVM、JRE和JDK的关系?


JDK

(java开发工具包)


Java Development Kit

是提供给Java开发人员使用的,其中包含了Java的开发工具和JRE。所以安装了JDK,就无需再单独安装JRE了。其中的

开发工具



编译工具(javac.exe)



打包工具(jar.exe)


JRE

(java运行时环境)

Java Runtime Environment包括

Java虚拟机

和Java程序所需的

核心类库

等。

核心类库

主要是java.lang包:包含了运行Java程序必不可少的系统类,如基本数据类型、基本数学函数、字符串处理、线程、异常处理类等,系统缺省加载这个包。

如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。


JVM

(java虚拟机)


Java Virtual Machine

是Java虚拟机,Java程序需要运行在虚拟机上,不同的平台有自己的虚拟机,因此Java语言可以实现跨平台。

在这里插入图片描述



2、如果main方法被声明为private会怎样?

main()使程序的主入口,也是程序必须运行的通道,所以声明private会报错。

public class Test {
    private static void main(String[] args) {
        System.out.println("Hello");
    }
}


结果:

编译没问题,执行报错。

错误: 找不到或无法加载主类 Test
原因: java.lang.NoClassDefFoundError: Algorithm/Test (wrong name: Test)



3、&和&&的区别在哪里?


&

:按位与(二进制按位与)


&&

:逻辑与,返回值为boolean.

public static void main(String[] args) {
   /*
       按位与,按二进制位进行与运算
       00000100    4
       00000101    5
       00000100结果为4
    */
   System.out.println(4 & 5);
   //&&短路运算:前面是false后边就不会计算
   System.out.println(false && (10 > 20));
}



4、char类型的变量可不可以存汉字?


答案:

是可以的,char类型中存储的是

Unicode编码

,Unicode编码中是存在中文的,所以Char自然可以存储汉字。

但是!仅限于Unicode中存在的汉字。一个汉字的占两个字节,一个Unicode也是占两个字节 ,char存储汉字完全没有问题。



5、a+=b 和a=a+b的区别?

  • 数字类型的常量在java里面默认都是int类型
  • short,byte类型的数相加,都会提升为int类型
public static void main(String[] args) {
   //数字类型的常量在java里面默认都是int类型
   //short,byte类型的数相加,都会提升为int类型
   short a = 10;
   short b = 8;
   //a = a+b;//编译报错:因为a+b结果是int,却赋值给了short a
   a = (short)(a+b);
   System.out.println(a);
    
    /*
      += : 是java中的一个运算符,而不是两个,
      所以在运算时会进行自动类型转换。所以在编译时没有报错。
    */
   a+=b;//正确!!
     
}



+=


: 是java中的一个运算符,而不是两个,所以在运算时会进行自动类型转换。所以在编译时没有报错。



6、不使用第三变量交换两个变量的值


public class Test01 {
	//方式一
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        a = a+b;
        b = a-b;
        a = a-b;
        System.out.println(a);//20
        System.out.println(b);//10
    }
	//方式二
	public static void main(String[] args) {
        int a = 10;
        int b = 20;
        a = a*b;
        b = a/b;
        a = a/b;
        System.out.println(a);//20
        System.out.println(b);//10
    }
	//方式三
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        //a = b+(b=a)*0;
        a = b-(b=a)*0;//从左往右
        System.out.println(a);//20
        System.out.println(b);//10
    }
}



7、String s = new String(“xyz”)创建了几个String Object?

一个或者两个。

在这里插入图片描述

在这里插入图片描述



8、hashcode和equals的关系

public class Test02HashCodeEquals {
    /**
     * Hash是散列的意思
     *      就是把任意长度的输入,通过散列算法变换成固定长度的输出,该输出就是散列值。
     *      1、不同关键字经过散列算法变换后可能得到同一个散列地址,这种现象称为碰撞,hash碰撞。
     *      2、如果两个hash值不同(前提是同一hash算法),那么这两个hash值对应原始数据必定不同。
     * @param args
     */
    public static void main(String[] args) {
        String s1 = "重地";
        String s2 = "通话";
        System.out.println(s1.hashCode());//1179395
        System.out.println(s2.hashCode());//1179395

        //hashcode的作用是为了获取哈希吗,也称为散列码,返回int类型的整数。

        /*
            1、hashcode的存在主要是为了提高在散列结构中查找的效率,在线性表中没有作用。
            2、两个相等对象,分别调用equals方法时都会返回true
            3、如果两个对象equals相等,则hashcode一定也是相同的。
            4、两个对象的hashcode相同,不代表两个对象就相同,只能说明这两个对象在散列存储结构中,存放于同一个位置。
            5、因此,equals方法被覆盖过,则hashcode方法也必须被覆盖。
            6、hashcode()的默认行为是对堆上的对象产生独特的值。
         */
    }
}

在这里插入图片描述



9、最大公约数算法

public class Test03 {
    public static void main(String[] args) {
        main1();
        main2();
    }
    
    public static void main1() {
        int a = 2;
        int b = 3;
        int min = a>b?b:a;

        int result=0;
        for (int i = min; i >1; i--) {
            if(a%i==0 && b%i==0){
                result=i;
                break;
            }
        }
        System.out.println("最大公约数是:"+result);
    }

    public static void main2() {
        int a = 5;
        int b = 7;
        int max = a>b?a:b;
        for (int i = max; i <=a*b ; i++) {
            if(i%a==0 && i%b==0){
                System.out.println("最小公倍数是:"+i);
                break;
            }
        }
    }
}



10、final, finally, finalize 的区别?


final


用于声明属性,方法和类, 分别表示属性不可变, 方法不可覆盖, 类不可继承.


finally


是异常处理语句结构的一部分,表示总是执行.


finalize




Object

类的一个方法,

在垃圾收集器执行的时候会调用被回收对象的此方法

,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等. JVM不保证此方法总被调用.



11、Java中的Math.round(-1.5)等于多少?

public static void main(String[] args) {
    //返回int,四舍五入
    System.out.println(Math.round(1.5));//2
    System.out.println(Math.round(1.2));//1
    System.out.println(Math.round(-1.5));//-1
    
    //向下取整,整浮点数
    System.out.println(Math.floor(-1.5));//-2.0
    System.out.println(Math.floor(1.5));//1.0
    System.out.println(Math.floor(1.6));//1.0

    //向上取整,整浮点数
    System.out.println(Math.ceil(-1.5));//-1.0
    System.out.println(Math.ceil(1.5));//2.0
    System.out.println(Math.ceil(-1.6));//-1.0
}



1、常见的几种运行时异常?

Q3:写出你最常见的5个RuntimeException?

  • java.lang.

    NullPointerException

    (空指针异常):调用了未经初始化的对象或者是不存在的对象。
  • java.lang.

    ClassNotFoundException

    (指定的类找不到):类的名称和路径加载错误;通常都是程序试图通过字符串来加载某个类时可能引发的异常。
  • java.lang.

    NumberFormatException

    (数字格式异常):字符型数据中包含非数字型字符。
  • java.lang.

    IndexOutOfBoundsException

    (数组下标越界异常):常见于操作数组对象时发生。
  • java.lang.

    IllegalArgumentException

    :方法传递参数错误。
  • java.lang.

    ClassCastException

    :数据类型转换异常。
  • java.lang.


    InterruptedException


    : (中断异常)当线程在活动之前或活动期间处于正在等待、休眠或占用状态且该线程被中断时,抛出该异常。有时候,一种方法可能希望测试当前线程是否已被中断,如果已被中断,则立即抛出此异常。下列代码可以达到这种效果:


IllegalArgumentException不合法的参数异常

一个简单的小例子:

package Test2;

import java.text.SimpleDateFormat;
import java.util.Date;

public class Test3 {

    public static void main(String[] args) {
        Date day = new Date();   
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
        String date = df.format(day);

        SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM");
        String format = dateFormat.format(date);
        System.out.println(format);
    }
}

运行会报错:

无法将给定的对象作为日期格式化,即因为传递了一个错误的参数。

Exception in thread "main" java.lang.IllegalArgumentException: Cannot format given Object as a Date
    at java.text.DateFormat.format(DateFormat.java:281)
    at java.text.Format.format(Format.java:140)
    at Test2.Test3.main(Test3.java:14)



2、 String、StringBuffer、StringBuilder 的区别?


可变性:


String类中使用字符数组保存字符串,

private final char value[]

,所以string对象是不可变的。

StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,

char[] value

,这两种对象都是可变的。


线程安全性:


StringBuffer是线程安全的,StringBuilder是线程不安全的,StringBuffer在StringBuilder的方法之上加了同步锁(

synchronized

)修饰,保证线程安全。但他们两个中的所有方法都是相同的。


性能

每次对String 类型进行修改的时候,都会生成一个新的String对象,然后将指针指向新的String 对象。

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

相同情况下使用StirngBuilder 相比使用StringBuffer 仅能获得10%~15% 左右的性能提升,但却要冒多线程不安全的风险。

StringBuilder , StringBuffer ,String 都是 final 的


对于三者使用的总结

如果要操作少量的数据用 = String

单线程操作字符串缓冲区 下操作大量数据 = StringBuilder

多线程操作字符串缓冲区 下操作大量数据 = StringBuffer


补充:

如果一个String类型的字符串,在编译时就可以确定是一个字符串常量,则编译完成之后,字符串会自动拼接成一个常量。此时String的速度比StringBuilder和StringBuffer的性能更好。


StringBuilder , StringBuffer ,String 都是

final

的,但是为什么StringBuilder , StringBuffer可以进行修改呢?

因为不可变包括的是,引用不可变以及对象不可变,而这三个都是属于引用不可变(也就是地址不要变,里面的内容随心所欲),而StringBuilder , StringBuffer 中都包含右append方法,可对对象中的内容进行增加。而String a=“123”+new String(“456”);实际上底层是用了一个StringBuffer 进行append;



3、基本数据类型有哪些,string是基本数据类型吗

Java 中的基本数据类型只有 8 个 :byte、short、int、long、float、double、char、boolean;

除了基本类型(primitive type),剩下的都是引用类型(referencetype),

Java 5 以后引入的枚举类型也算是一种比较特殊的引用类型。


String的引入


Java 的 8 种基本数据类型中不包括 String,基本数据类型中用来描述文本数据的是 char,但是它只能表示单个字符,比如 ‘a’,‘好’ 之类的,如果要描述一段文本,就需要用多个 char 类型的变量,也就是一个 char 类型数组,比如“你好” 就是长度为2的数组 char[] chars = {‘你’,‘好’};

但是使用数组过于麻烦,所以就有了 String,String 底层就是一个 char 类型的数组,只是使用的时候开发者不需要直接操作底层数组,用更加简便的方式即可完成对字符串的使用。



5、过滤器和拦截器区别


过滤器

:是 servlet 规范中的一部分,任何 java web 工程都可以使用。在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。


拦截器

:是SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。它是只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image 或者 js 是不会进行拦截的。



6、String s = “hello”和String s = new String(“hello”);区别



String s = new String("hello");


可能创建两个对象也可能创建一个对象。如果常量池中有hello字符串常量的话,则仅仅在堆中创建一个对象。如果常量池中没有hello对象,则堆上和常量池都需要创建。



String s = "hello"


这样创建的对象,JVM会直接检查字符串常量池是否已有”hello”字符串对象,如没有,就分配一个内存存放”hello”,如有了,则直接将字符串常量池中的地址返回给栈。(没有new,没有堆的操作)



7、一个java程序是怎样运行起来的?

  • 程序员写.java
  • 编译成.class
  • 启动主线程
  • 类加载器启动
  • 加载main方法存在的类
  • 之后就是遇到一个类 加载一个class文件
  • 方法存在在方法栈中,参数存在堆会和栈中



8、什么时候会用到单例模式?

  • 在应用场景中,

    某类只要求生成一个对象的时候

    ,如一个班中的班长、每个人的身份证号等。

  • 当对象需要被共享的场合

    。由于单例模式只允许创建一个对象,共享该对象可以节省内存,并加快对象访问速度。如 Web 中的配置对象、数据库的连接池等。

  • 当某类需要频繁实例化,而创建的对象又频繁被销毁的时候

    ,如多线程的线程池、网络连接池等。



9、JDK1.5之前,switch循环只支持char、byte、short、int四种数据类型。

JDK1.5开始,switch循环中增加了枚举类与byte short char int的包装类,对四个包装类的支持是因为java编译器在底层手动进行拆箱,而对枚举类的支持是因为枚举类有一个ordinal方法,该方法实际上是一个int类型的数值。

JDK1.5之后支持的类型:char、byte、short、int 、Character、Byte、Short、Integer 、枚举。

JDK1.7开始,switch循环支持String类型,但实际上String类型有一个hashCode算法,结果也是int类型.而byte short char类型可以在不损失精度的情况下向上转型成int类型.所以总的来说,可以认为switch中只支持int。JDK1.7之后支持的类型:char、byte、short、int 、Character、Byte、Short、Integer 、String、枚举。

注:switch中,表达式不能为空,为空会抛出NullPointerException。case项即不能为空也不能重复,这两种情况都会出现编译错误。



版权声明:本文为qq_42390340原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。