java面试题

      final 有什么用?

  • 被final修饰的类不可以被继承
  • 被final修饰的方法不可以被重写
  • 被final修饰的变量不可以被改变,被final修饰不可变的是变量的引用地址,地址中的内容是可以改变的。
    final int b=3;
    b=2;//将报错

    static存在的主要意义

  • static的主要意义是在于创建独立于具体对象的域变量或者方法。以致于即使没有创建对象,也能使用属性和调用方法!

  • static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。

  • 为什么说static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次。因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。

    public class user {
        static {
            System.out.println("123");
        }
    }
    public class test2 {
        public static void main(String[] args) {
            user u1=new user();
            user u2=new user();
        }
    }

    控制台只会输出一次 123

    在 Java 中,如何跳出当前的多重嵌套循环

  • 在Java中,要想跳出多重循环,可以在外面的循环语句前定义一个标号,然后在里层循环体的代码中使用带有标号的break 语句,即可跳出外层循环。例如:
  • public class test3 {
        public static void main(String[] args) {
            ok:
            for(int i=0;i<10;i++){
                for(int j=0;j<10;j++){
                    System.out.println(j);
                    if(j==5){
                        break ok;
                    }
    
                }
            }
        }
    }

    面向对象的特征主要有以下几个方面

  • 继承:是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码。

  • 多态:父类引用指向子类对象,调用方法时会调用子类的实现,而不是父类的实现,这叫多态。

  • public class Animal {
        int a=10;
        static int b=20;
        public void eat(){
            System.out.println("动物吃饭");
        }
        public static void sleep(){
            System.out.println("动物睡觉");
        }
        public void play(){
            System.out.println("动物玩游戏");
        }
    
    }
    
    public class Cat extends Animal{
        int a=50;
        static int b=60;
        public void eat(){
            System.out.println("猫咪吃饭");
        }
        public static void sleep(){
            System.out.println("猫咪睡觉");
        }
    
    }
    
    public class test {
        public static void main(String[] args) {
            Animal animal=new Cat();
            animal.eat();
            animal.play();
            animal.sleep();
            System.out.println(animal.a);
            System.out.println(animal.b);
    
        }
    }
    猫咪吃饭
    动物玩游戏
    动物睡觉
    10
    20
    变量(包括静态与非静态):编译看左运行看左
    非静态方法:编译看左,运行看右边
    静态方法:编译看左运行看左

    如果想使用子类变量和静态方法:

  • public class test {
        public static void main(String[] args) {
            Animal animal=new Cat();
            Cat cat= (Cat) animal;
            cat.eat();
            cat.play();
            cat.sleep();
            System.out.println(cat.a);
            System.out.println(cat.b);
    
        }
    }
    猫咪吃饭
    动物玩游戏
    猫咪睡觉
    50
    60
    

     

  •  

    关于继承特点

    1.子类拥有父类非 private 的属性和方法。

     

    2.子类可以拥有自己属性和方法,即子类可以对父类进行扩展。

    3.子类可以用自己的方式实现父类的方法。

  •  

    封装:把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法

抽象类和接口的对比

相同点:

  • 都位于继承的顶端,用于被其他实现或继承
  • 都包含抽象方法,其子类都必须覆写这些抽象方法

不同点:

抽象类中抽象方法必须加abstract,接口可以省略。

成员变量与局部变量

  • 成员变量:随着对象的创建而存在,随着对象的消失而消失,存储在堆内存中。
  • 局部变量:在方法被调用,或者语句被执行的时候存在,如果是基本数据类型存储在栈内存中,如果是是对象,对象的引用存储在栈内存中。当方法调用完,或者语句结束后,就自动释放。
  • 成员变量:有默认初始值。
  • 局部变量:没有默认初始值,使用前必须赋值。

构造方法

  • 名字与类名相同;
  • 没有返回值,但不能用void声明构造函数;
  • 生成类的对象时自动执行,无需调用。
  • 关于继承:Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用super()来调用父类中特定的构造方法,则编译时将发生错误,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。如果父类只有有参构造,那么子类也只能有有参构造
    package test;
    
    public class test1 {
        int a;
        public test1(int a) {
            this.a=a;
        }
    }
    package test;
    
    public class test2 extends test1{
        
        public test2(int a) {
            //不实现父类有参构造将会报错
            super(a);
        }
    }

    静态变量和实例变量区别

  • 静态变量: 静态变量由于不属于任何实例对象,属于类的,所以在内存中只会有一份(在方法区),在类的加载过程中,JVM只为静态变量分配一次内存空间。
  • 实例变量: 每次创建对象,都会为每个对象分配成员变量内存空间,实例变量是属于实例对象的(对象实例在堆内存),在内存中,创建几次对象,就有几份成员变量。

   在一个静态方法内调用一个非静态成员为什么是非法的?

  • 静态方法在类第一次被调用时就被加载到内存方法区中,这时就可以调用,此时类还没初始化所有静态成员还没初始化,所有调用是非法的

   内部类

  • 在Java中,可以将一个类的定义放在另外一个类的定义内部,这就是内部类。内部类本身就是类的一个属性,与其他属性定义方式一致
  • 内部类可以分为四种:成员内部类、局部内部类(定义在方法中的内部类)、匿名内部类和静态内部类
  • public class Outer {
    
        private void test(final int i) {
            new Service() {
                public void method() {
                    for (int j = 0; j < i; j++) {
                        System.out.println("匿名内部类" );
                    }
                }
            }.method();
        }
     }
     //匿名内部类必须继承一个类或实现一个已有的接口 
     interface Service{
        void method();
    }
    

     

  • 匿名内部类必须继承一个抽象类或者实现一个接口。
  • 匿名内部类不能定义任何静态成员和静态方法。
  • 当所在的方法的形参需要被匿名内部类使用时,必须声明为 final。
  • 匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。

 == 和 equals和hashCode (重点理解)

  • == : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象。(基本数据类型 == 比较的是值,引用数据类型 == 比较的是内存地址)
  • equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:

    情况1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。

    情况2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来两个对象的内容相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。

  • 两个对象有相同的hashcode值(hashcode方法被重写),它们也不一定是相等的

  • 超类的hashCode 返回的是对象的地址

  • HashSet方法存入对象时,先比较对象的hashCode(hashcode方法被重写,例如用%3取余映射,如果映射不同则值肯定不同)是否相同,如果不同则不相等,如果相同,则调用equals(equals方法也被重写,此时比较对象中值)比较是否相等。

   Java 中只有值传递

  • 如果是基本数据类型,值传递不会改变其原有值
  • 如果是对象,会改变原有对象
  • 值传递和引用传递有什么区别

值传递:指的是在方法调用时,传递的参数是按值的拷贝传递,传递的是值的拷贝,也就是说传递后就互不相关了。

引用传递:指的是在方法调用时,传递的参数是按引用进行传递,其实传递的引用的地址,也就是变量所对应的内存空间的地址。传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)
 

  • public static void main(String[] args) {
        int num1 = 10;
        int num2 = 20;
    
        swap(num1, num2);
    
        System.out.println("num1 = " + num1);
        System.out.println("num2 = " + num2);
    }
    
    public static void swap(int a, int b) {
        int temp = a;
        a = b;
        b = temp;
    
        System.out.println("a = " + a);
        System.out.println("b = " + b);
    }
    
    a = 20
    b = 10
    num1 = 10
    num2 = 20

    img

     

    public static void main(String[] args) {
            int[] arr = { 1, 2, 3, 4, 5 };
            System.out.println(arr[0]);
            change(arr);
            System.out.println(arr[0]);
        }
    
        public static void change(int[] array) {
            // 将数组的第一个元素变为0
            array[0] = 0;
        }
    
    1
    0

    img

 

反射三种实现:

public class Get {
    //获取反射机制三种方式
    public static void main(String[] args) throws ClassNotFoundException {
        //方式一(通过建立对象)
        Student stu = new Student();
        Class classobj1 = stu.getClass();
        System.out.println(classobj1.getName());
        //方式二(所在通过路径-相对路径)
        Class classobj2 = Class.forName("fanshe.Student");
        System.out.println(classobj2.getName());
        //方式三(通过类名)
        Class classobj3 = Student.class;
        System.out.println(classobj3.getName());
    }

什么是字符串常量池?

  • 字符串常量池位于堆内存中,专门用来存储字符串常量,可以提高内存的使用率,避免开辟多块空间存储相同的字符串,在创建字符串时 JVM 会首先检查字符串常量池,如果该字符串已经存在池中,则返回它的引用,如果不存在,则实例化一个字符串放到池中,并返回其引用。

是否可以继承 String 类

  • String 类是 final 类,不可以被继承。

String str="i"与 String str=new String(“i”)一样吗?

  • 不一样,因为内存的分配方式不一样。String str="i"的方式,java 虚拟机会将其分配到常量池中;而 String str=new String(“i”) 则会被分到堆内存中。

 

 包装类相关

  • 原始类型: boolean,char,byte,short,int,long,float,double
  • 包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值