面试题—JAVA基础9.19/20

目录

try-catch

总结:

局部变量和实例变量

 final

问:JDBC为什么是桥接模式?

多线程

串池

 static

从哪能获取cookie值?

Cookie和Session 

四大作用域 

内部类

 修饰符

对String和作用域的思考

super()和this()

溢出


 

try-catch

当Java程序中执行try-catch时遇到了retrun语句或者throw语句,会导致立即结束——>如果有finally的话,只有当finally块执行完结束后,再回来执行try-catch中的return;如果finally中也有return的话,那么finally执行完后就不会再返回try-catch中的return了

例题2

 

答案:1201 

总结:

1、不管有木有出现异常,finally块中代码都会执行;

2、当try和catch中有return时,finally仍然会执行;
3、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的;
4、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。
举例:

情况1:try{} catch(){}finally{} return;

显然程序按顺序执行。

情况2:try{ return; }catch(){} finally{} return;

程序执行try块中return之前(包括return语句中的表达式运算)代码;
再执行finally块,最后执行try中return;
finally块之后的语句return,因为程序在try中已经return所以不再执行。

情况3:try{ } catch(){return;} finally{} return;

程序先执行try,如果遇到异常执行catch块,
有异常:则执行catch中return之前(包括return语句中的表达式运算)代码,再执行finally语句中全部代码,
最后执行catch块中return. finally之后也就是4处的代码不再执行。
无异常:执行完try再finally再return.

情况4:try{ return; }catch(){} finally{return;}

程序执行try块中return之前(包括return语句中的表达式运算)代码;
再执行finally块,因为finally块中有return所以提前退出。

情况5:try{} catch(){return;}finally{return;}

程序执行catch块中return之前(包括return语句中的表达式运算)代码;
再执行finally块,因为finally块中有return所以提前退出。

情况6:try{ return;}catch(){return;} finally{return;}

程序执行try块中return之前(包括return语句中的表达式运算)代码;
有异常:执行catch块中return之前(包括return语句中的表达式运算)代码;
则再执行finally块,因为finally块中有return所以提前退出。
无异常:则再执行finally块,因为finally块中有return所以提前退出。
最终结论:任何执行try 或者catch中的return语句之前,都会先执行finally语句,如果finally存在的话。
如果finally中有return语句,那么程序就return了,所以finally中的return是一定会被return的,

编译器把finally中的return实现为一个warning。

局部变量和实例变量

 实例变量:就是我们的全局变量,它是默认初始化的,有默认值

 局部变量:形参这种,必须要初始化

 final

1.final修饰的方法,方法是不能重写的——>但是可以重载

2.final修饰的类不可继承,所以接口,抽象类这些是不能final修饰的也没什么意义

 桥接模式

问:JDBC为什么是桥接模式?

前景:这跟它的设计有关,我们不同数据库传输协议那些都不同,也就是Driver不同——>那么我们难道Java要为每一种数据库都要写一个接口去支持数据库厂商的实现吗?

那肯定不行,所以用到了桥接模式

try {
            Class.forName("com.mysql.jdbc.Driver");
            String url = "";
            String user = "";
            String password = "";
            Connection con = DriverManager.getConnection(url, user, password);
        } catch (Exception e) {

        }

像我们正常的话就是继承实现,但是你每多一个数据库,子类就会成指数型增长——>用组合的方式实现

比如我们这里的JDBC——>这里Java做的是提供一套接口让厂商自己实现,一套接口给程序开发者调用,两者的结合就是经典的桥接模式

这里写图片描述

 DriverManager是个Driver容器(连接),管理不同的Driver,每次执行Class.forName()的时候,大家可以看到有一块静态static 代码,执行了具体Driver向DriverManager注册注入的过程:这样具体的数据Driver实现就统一交给容器管理,执行验证连接,获取连接的操作

public class Driver extends NonRegisteringDriver implements java.sql.Driver {

    // Register ourselves with the DriverManager
    //
    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }

例子:

我们前面这些conn连接就是面向用户,DriverManager就是连接,后面的api就是面向数据库厂商

public class jdbcTest {
    public static void main(String[] args) {
        try {
            //加载数据库驱动jar包
            ///mysql8版本:com.mysql.cj.jdbc.Driver
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //第一个参数:数据库连接
        //第二个参数:用户名
        //第三个参数:密码
        String url="jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8";
        try {
            //获取数据库链接对象
            Connection connection=DriverManager.getConnection(url,"root","root");
            System.out.println("连接成功"+ connection);
            //获取执行sql语句的对象
            Statement statement=connection.createStatement();
//            增加
//            String sql="insert into student values(null,'张三',19,'男',now())";
//            修改
//            String sql="update student set name='李四',age=22 where stuid=1";
//            删除
//            String sql="delete from student where stuid=1";
//            增删改都要用这个方法,
//            statement.executeUpdate(sql);
//            System.out.println("修改成功");
//            查询
            String sqll="select * from student";
//            查询得到的结果集
            ResultSet resultSet = statement.executeQuery(sqll);
            System.out.println();
            while (resultSet.next()){
//                columnlabel:通过字段名称查询
//                columnindex:通过字段位置查询
                System.out.print(resultSet.getInt(1)+"\t");
                System.out.print(resultSet.getString("name")+"\t");
                System.out.print(resultSet.getInt(3)+"\t");
                System.out.println(resultSet.getString("sex")+"\t");
                System.out.println(resultSet.getInt(5));
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}

多线程

 

每个线程一定是先打印0-4,最后再打印空格,所以说空格的出现代表前面一定有0-4的出现,所以选c 

串池

一般都是问new Strng("abc")创建几个对象这种,我统一来说说

String s="abc": 通过字面量赋值创建字符串。则将栈中的引用直接指向该字符串,如不存在——>则在常量池中生成一个字符串,再将栈中的引用指向该字符串(创建0-1个对象)

String s="a"+"bc": 编译阶段会直接将“a”和“bc”结合成“abc”,这时如果方法区已存在“abc”,则将s的引用指向该字符串,如不存在,则在方法区中生成字符串“abc”对象,然后再将s的引用指向该字符串

String s="a"+new String("bc"): 像new的话会先在串池中看有没有,没有就在串池中来一个对象,然后再在堆中创建一个,并且引用指向堆中的——>(创建1-2个对象)
String s = "a" + new String("bc"):栈中先创建一个"a"字符串常量,再创建一个"bc"字符串常量,编译阶段不会进行拼接,在运行阶段拼接成"abc"字符串常量并将s的引用指向它,效果相当于String s = new String("abc"),只有'+'两边都是字符串常量才会在编译阶段优化

 

 static

1.类名直接访问,不能this调用——>this和super不能一起用,都是掉父类会引起资源浪费现象,并且必须第一行

2.静态代码块在类加载时指向一次

3.实例对象时可以调用静态方法的

package com.wyh.SE.lc.Test;

public class test01 {
    public static void test(){
        System.out.println("11");
    }
    public static void main(String[] args) {
        test01 t = new test01();
        t.test();
    }
}

从哪能获取cookie值?

 request.getParameter()取得是通过容器的实现来取得通过类似post,get等方式传入的数据(参数),request.setAttribute()和getAttribute()只是在web容器内部流转,仅仅是请求处理阶段(请求域)

两个WEB间为转发关系时,转发目的WEB可以用getAttribute()方法来和转发源WEB共享request范围内的数据

Cookie和Session 

(38条消息) 从Http思考项目中的cookie和session+ServletContext_Fairy要carry的博客-CSDN博客

四大作用域 

(38条消息) 从Http思考项目中的cookie和session+ServletContext_Fairy要carry的博客-CSDN博客

(38条消息) 什么是会话_墨时澈℡的博客-CSDN博客_会话 

内部类

 成员内部类:可以访问外部所有资源,本身自己就是要依靠外部类进行实例化——>所以自己里面是不能有static属性的

 局部内部类:只能访问final变量和形参,因为一般在外部类的一般方法中

 匿名内部类:创建的时候一般跟个new,没有类名构造器,所以是没有static资源,毕竟连类名都没有

另外我们非静态内部类是可以访问外部类所有权限字段的,通过invokestatic执行外部类的static方法access得到外部类对象构造方法

——>所以说我们静态内部类不依靠外部类存在,得不到外部类的引用

然后还有些内存泄漏的情况也要注意,static字段为root引用回收不了,然后注意非静态内部类持有外部类引用如果没有被

(39条消息) Java基础面试题_Fairy要carry的博客-CSDN博客

 修饰符

default: 指默认权限,也叫包访问权限,只能在包中访问

public:公开访问,所有地方

protected:可以在其他包中访问,但前提是有继承关系。。

private:只能在当前类中访问

对String和作用域的思考

package com.wyh.SE.lc.Test;

public class Example{
    String str=new String("tarena");
    char[]ch={'a','b','c'};
    public static void main(String args[]){
        Example ex=new Example();
        ex.change(ex.str,ex.ch);
        System.out.print(ex.str+" and ");
        System.out.print(ex.ch);
    }
    public void change(String str,char ch[]){
   //引用类型变量,传递的是地址,属于引用传递。
        str="test ok";
        ch[0]='g';
    }
}

问结果是多少?

解决:字符串的实例存在在串池中(锁定了资源不被篡改),是不可变的,而代码上str的指向只是在change方法中发生了改变,所以说出了change方法,结果就变了;而char数组是会改变原值的,资源并没有被锁定

super()和this()

super()必须在第一行的原因是: 子类是有可能访问父类对象的, 比如在构造函数中使用父类对象的成员函数和变量, 在成员初始化使用了父类, 在代码块中使用了父类等等, 所以为保证在子类可以访问父类对象之前,一定要完成对父类对象的初始化(第一行默认super())。   关于this()必须在第一行的原因,我们假设这样一种情况,,类B是类A的子类, 如果this()可以在构造函数的任意行使用, 那么当程序运行到构造函数B()的第一行,发现没有调用this()和super(),那么就会自动在第一行补齐super() 来完成对父类对象的初始化, 然后返回子类的构造函数继续执行, 当运行到构造函数B()的"this() ;"时, 调用B类对象的构造函数, 还会对父类对象再次初始化!,这就造成了资源的浪费,以及某些意想不到的错误。也正因如此C选项错误。

D选项,无论是this()还是super()指的都是对象,而static环境中是无法使用非静态变量的。因此D选项错误

溢出

 

java中只有byte, boolean是一个字节, char是两个字节, 所以对于java来说127不会发生溢出, 输出328

boolean也可能占四个字节,因为JVM识别不了boolean,编译后会用int来代替——>一字节8位,byte1位,int4位,所以boolean也可能四位

如果boolean是单独使用:boolean占4个字节——>boolean在底层实际会调用int,那么既然int占4个字节,boolean也自然占4个字节。即,boolean类型占4个字节

如果boolean是以“boolean数组”的形式使用:boolean占1个字节——>boolean数组在底层会用到byte指令,那么既然byte占1个字节,boolean数组中的boolean也就占1个字节。即,boolean数组中的boolean占1个字节

但是对于c/c++语言来说, char是一个字节, 会发生溢出, 对127加一发生溢出,  0111 1111 --> 1000 0000, 1000 0000为补码-128, 所以结果为200-128=72

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fairy要carry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值