注意点

作者: luckee | 来源:发表于2019-01-08 04:50 被阅读0次

    不使用IDE怎么编译和指定classpath

    private default protected public

    image.png

    注意:java的访问控制是停留在编译层的,也就是它不会在.class文件中留下任何的痕迹,只在编译的时候进行访问控制的检查。其实,通过反射的手段,是可以访问任何包下任何类中的成员,例如,访问类的私有成员也是可能的。

    Arrays.asList的用法

    使用工具类Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的add/remove/clear方法会抛出UnsupportOperationException异常
    说明:asList的返回对象是一个Arrays内部类,并没有实现集合的修改方法。Arrays.asList体现的是适配器模式,只是转换接口,后台的数据仍是数组。
    String[] str = new String[]{"1","2"};
    List list = Arrays.asList(str);
    第一种情况:list.add("x");//运行时异常
    第二种情况:str[0] = "unv";//那么list.get(0)也随着修改。
    此类包含用来操作数组(比如排序和搜索)的各种方法。此类还包含一个允许将数组作为列表来查看的静态工厂。 除非特别注明,否则如果指定数组引用为 null,则此类中的方法都会抛出 NullPointerException。一段有意思的代码如下:
    Java代码

    public static void main(String[] args) {
    
    int[] data = {1,2,3,4,5};
    
    List list = Arrays.asList(data);
    
    System.out.println("列表中的元素数量是:" + list.size());
    
    }
    

    注意这里输出的数量是1,原因是,在Arrays.asList中,该方法接受一个变长参数,一般可看做数组参数,但是因为int[] 本身就是一个类型,所以data变量作为参数传递时,编译器认为只传了一个变量,这个变量的类型是int数组,所以size为1。基本类型是不能作为泛型的参数,按道理应该使用包装类型,但这里缺没有报错,因为数组是可以泛型化的,所以转换后在list中就有一个类型为int的数组

    public class ClearRepeatTest {
         
        public static Integer[] clearRepeat(int [] array){
            Set<Integer> set = new HashSet<>();
            for(int i : array){
                set.add(i);
            }
            Integer[] newArray = set.toArray(new Integer[set.size()]);
            return newArray;
        }
         
         
        public static void main(String[] args) {
            //创建一个数组,可以看出 2和4 是重复的
            int [] array = {1,2,3,4,8,2,5,4};
            Integer[] newArray = clearRepeat(array);
            for(Integer i : newArray){
                System.out.println(i);
            }
            //1 2 3 4 5 8
             
        }
     
    }
    

    ==和equals

    ==比较的是两个操作数的值是否相等,对于基本类型变量和引用类型变量都是比较变量的值是否相等。对于基本类型的变量好理解,对于引用类型的变量,其本身也是变量,有自己的内存空间,存的是其引用的对象的堆空间地址。equals比较的是对象的内容是否一样,并不一定是同一个对象内容才相同,不同的对象内容也可能相同。

    &&和&的区别(||和|也一样)

    都可以是逻辑运算操作符,此时&&具有短路功能;除此之外,当操作数不是boolean值时,&则表示按位与

    数据库表可以没有主键吗

    可以

    HashMap的四种遍历

    • ①获取keyset和values
    • ②先获取keyset,然后通过get(key)获取value
    • ③获取entryset,然后for-in遍历
    • ④获取entryset,然后通过迭代器Iterator遍历
    • ②的效率很低,不建议使用。③的效率高。④的效率也不错,可以在遍历的时候删除元素,①适合在单独需要keyset或values的情况

    transient

    Java中transient关键字的作用,简单地说,就是让某些被修饰的成员属性变量不被序列化,这一看好像很好理解,就是不被序列化,那么什么情况下,一个对象的某些字段不需要被序列化呢?如果有如下情况,可以考虑使用关键字transient修饰:

    1、类中的字段值可以根据其它字段推导出来,如一个长方形类有三个属性:长度、宽度、面积(示例而已,一般不会这样设计),那么在序列化的时候,面积这个属性就没必要被序列化了;

    2、其它,看具体业务需求吧,哪些字段不想被序列化;

    PS,记得之前看HashMap源码的时候,发现有个字段是用transient修饰的,我觉得还是有道理的,确实没必要对这个modCount字段进行序列化,因为没有意义,modCount主要用于判断HashMap是否被修改(像put、remove操作的时候,modCount都会自增),对于这种变量,一开始可以为任何值,0当然也是可以(new出来、反序列化出来、或者克隆clone出来的时候都是为0的),没必要持久化其值。

    对象复制

    浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。

    深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制,而浅复制不彻底。

    public class Prototype implements Cloneable, Serializable {
     
        private static final long serialVersionUID = 1L;
        private String string;
     
        private SerializableObject obj;
     
        /* 浅复制 */
        public Object clone() throws CloneNotSupportedException {
            Prototype proto = (Prototype) super.clone();
            return proto;
        }
     
        /* 深复制 */
        public Object deepClone() throws IOException, ClassNotFoundException {
     
            /* 写入当前对象的二进制流 */
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
     
            /* 读出二进制流产生的新对象 */
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            return ois.readObject();
        }
     
        public String getString() {
            return string;
        }
     
        public void setString(String string) {
            this.string = string;
        }
     
        public SerializableObject getObj() {
            return obj;
        }
     
        public void setObj(SerializableObject obj) {
            this.obj = obj;
        }
     
    }
     
    class SerializableObject implements Serializable {
        private static final long serialVersionUID = 1L;
    }
    
    

    一个类是否可以调用其他类的main

    一个类是否可以调用其他类的main

    基本类型变量存在哪

    基本数据类型存在于虚拟机栈区,基本数据类型的存储形式既不是对象引用,也不是地址,而是就是值本身。
    在虚拟机栈区中,除了基本数据类型以外,还存在着对象的引用。这些引用就指向了堆区中的实际对象值。

    类A有个字段是类B类型的,那么A类型的对象在堆空间地址范围中包含一个B类型的对象还是对象引用

    我觉得在为A的对象分配空间的时候,计算需要申请多大的内存,应该算的是基本类型和String类型(因为String是不可变类),引用类型的字段应该用一种能够表示内存地址的类型(比如用一个int来表示一个地址)来表示,存放的值为B类型的对象在堆中的地址

    如何计算对象的占用空间大小

    计算对象空间大小

    1. 通过java.lang.instrument.Instrumentation的getObjectSize(obj)直接获取对象的大小

    2. 通过sun.misc.Unsafe对象的objectFieldOffset(field)等方法结合反射来计算对象的大小

    main方法结束了,程序就结束了吗

    不是的,main方法所在的线程是主线程,各个线程之间没有关系,main方法结束了,其他线程完全可能还在运行

    接口继承了Object吗

    没有。下面这段话是Oracle官方描述

    If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throwsclause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless a method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface.

    如果一个接口定义是最顶级的(没有 super interfaces),那么这个接口会自动声明一个 abstract member method 结构体来代表所有来自 Object 类(一切类的superclass)中的public方法(包括这些方法的签名、返回类型以及抛出的异常)再换种说法——意思是接口隐含定义了一套与Object类中的方法签名完全相同的方法,所以,我们在程序中调用接口的那些与Object中具有相同签名的方法时,编译器不会报错!好处是让接口型的(interface Type)父类引用也可以拥有Object类的一般方法( toString()、equals() 等)

    接口的默认

    接口中的成员变量默认由 public static final 来修饰的, 而接口中成员方法前使用 public abstract 来修饰。 image.png

    如何跳出当前的多重嵌套循环

    为循环打标记,例如

    outer:
    for(int i = 0;i<10;i++) {
      inner:
      for(int j = 0;j<10;j++) {
          if(j == 5) 
            break outer;
      }
    }
    

    活用位运算

    恰当的时候使用位运算来做乘法/除法,能提高速度,因为CPU直接支持位运算。

    亦或运算

    自己跟自己进行亦或运算结果为0。跟全1与运算得到自己,跟全0或运算得到自己

    溢出

    进行数值运算时要考虑溢出的可能

    使用final修饰的变量

    final修饰的变量,变量本身的值不能变,但是引用的对象的内容可以改变(不可变类除外)

    ArrayList,Vector,LinkedList的存储性能和特性

    ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较 ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即 可,所以插入速度较快

    final, finally, finalize的区别。

    final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。finally是异常处理语句结构的一部分,表示总是执行。finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。

    Overload和Override的区别。Overload的方法是否可以改变返回值的类型?

    方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现, 重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。如果在一个类中定义了多个同名的方 法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型。

    forward 和redirect的区别

    • forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址。
    • redirect就是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,一般来说浏览器会用刚才请求的所有参数重新请求,所以session,request参数都可以获取。

    接口是否可继承接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concrete class)?抽象类中是否可以有静态的main方法?

    接口可以继承接口。抽象类可以实现(implements)接口,抽象类可以继承具体类。抽象类中可以有静态的main方法。只要记住抽象类与普通类的唯一区别:就是不能创建实例对象和允许有abstract方法(也可以没有)。

    native

    native方法表示该方法要用另外一种依赖平台的编程语言实现的,不存在着被子类实现的问题,所以,它也不能是抽象的,不能与abstract混用。例如,FileOutputSteam类要硬件打交道,底层的实现用的是操作系统相关的api实现,例如,在windows用c语言实现的,所以,查看jdk的源代码,可以发现FileOutputStream的open方法的定义如下:
    private native void open(Stringname) throws FileNotFoundException;
    如果我们要用java调用别人写的c语言函数,我们是无法直接调用的,我们需要按照java的要求写一个c语言的函数,用我们的这个c语言函数去调用别人的c语言函数。由于我们的c语言函数是按java的要求来写的,我们这个c语言函数就可以与java对接上,java那边的对接方式就是定义出与我们这个c函数相对应的方法,java中对应的方法不需要写具体的代码,但需要在前面声明native。

    try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后

    会执行,在return前执行

    Iterator和ListIterator的区别是什么?

    Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。
    Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。
    ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。

    内部类

    内部类可以访问外部类的数据域,因为内部类包含了一个对外部类的引用“外部类.this”;外部类定义了一个内部类,并不意味着每个外部类对象都有一个内部类对象

    根据位置不同分为下面几种情况(内部类包含了一个对外部类的引用“外部类.this”):

    1. (普通)成员内部类。类似于外部类的数据域/方法的位置,可以访问外部类的所有数据域和方法,可以用public,private修饰;如果是public修饰,在外面可以这样使用公有内部类,假设A内定义了一个B类,A a = new A(); A.B b = a.new B();

    2. 静态(成员)内部类。跟成员内部类不同的是,有static修饰符,只能访问外部类的静态数据域和静态方法

    3. 局部内部类。定义在外部类的方法内,不可以public,private修饰,而且只有在该方法内可见,对外部隐藏起来,就算是外部类的其他方法也不可见。局部内部类可以访问外部类的所有数据域和方法,但是只能访问所在方法中final修饰的局部变量,不能访问所在方法中的非final局部变量

    4. 匿名内部类。其实是临时类,因为只是在此时需要一个特定对象而建的一个临时类,用完即走,也就用这么一次,所以没必要单独写个类文件,而且实际上是创建了一个内部类对象,new SuperClass(parameters) {....}或者new Interface(){...},接口的时候没有参数

    硬链接和软链接

    • 硬链接(Hard Link)指通过索引节点来进行连接,在Linux为文件系统中,保存在磁盘分区中的文件不管是什么类型都给它分配一个编号,称为索引节点号; 硬链接指的就是在Linux中,多个文件名指向同一索引节点; 常见用途:通过建立硬链接到重要文件,防止误删,删除其实对应的是删除其中的一个硬链接,当文件对应的硬链接都被删除了,该文件才真正被删除; 硬链接是同一文件的不同访问路径,其对应的索引节点号是一样的。

    • 软链接(Symbolic Link)也称为符号链接,类似于Windows的快捷方式,其中包含的是另一个文件的位置信息,删除符号链接不影响源文件,删除源文件,则对应的符号链接也没有意义;

    • 只能在同种存储媒体上的文件之间创建硬链接(Hard Link),不能在不同挂载点下的文件间创建硬链接,对于后一种情况,可以使用软链接(区分不同挂载点与同一挂载点不同目录) ;

    • 创建硬链接命令:cp -l 1.txt 2.txt等同于ln 1.txt 2.txt为1.txt建立硬链接2.txt;创建符号链接命令:cp -s 2.txt sLink 等同于ln –s 2.txt sLink为2.txt文件建立符号链接sLink

    • switch语句能否作用在byte上,能否作用在long上,能否作用在String上?
      在switch(expr1)中,expr1只能是一个整数表达式或者枚举常量,整数表达式可以是int基本类型或Integer包装类型,由于,byte,short,char都可以隐含转换为int,所以,这些类型以及这些类型的包装类型也是可以的。显然,long和String类型都不符合switch的语法规定,并且不能被隐式转换成int类型,所以,它们不能作用于swtich语句中。

    • short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
      对于short s1 = 1; s1 = s1 + 1; 由于s1+1运算时会自动提升表达式的类型,所以结果是int型,再赋值给short类型s1时,编译器将报告需要强制转换类型的错误。对于short s1 = 1; s1 += 1;由于+=是java语言规定的运算符,java编译器会对它进行特殊处理,因此可以正确编译。

    • char型变量中能不能存贮一个中文汉字?为什么?
      char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包含了汉字,所以,char型变量中当然可以存储汉字啦。不过,如果某个特殊的汉字没有被包含在unicode编码字符集中,那么,这个char型变量中就不能存储这个特殊汉字。补充说明:unicode编码占用两个字节,所以,char类型的变量也是占用两个字节。

    • 静态变量和实例变量的区别?
        在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。

    • 请说出作用域public,private,protected,以及不写时的区别
      这四个作用域的可见范围如下表所示。
      说明:如果在修饰的元素上面没有写任何访问修饰符,则表示friendly。


      image.png
    • ClassLoader如何加载class?
        jvm里有多个类加载器,每个类加载器可以负责加载特定位置的类,例如,bootstrap类加载负责加载jre/lib/rt.jar中的类, 我们平时用的jdk中的类都位于rt.jar中。extclassloader负责加载jre/lib/ext/*.jar中的类,appclassloader负责classpath指定的目录或jar中的类。除了bootstrap之外(C语言实现),其他的类加载器本身也都是java类,它们的父类是URLClassLoader。

    • hashCode方法的作用?
        hashcode这个方法是用来鉴定2个对象是否相等的。equals方法和hashCode方法这2个方法都是用来判断2个对象是否相等的,但是他们是有区别的。一般来讲,equals这个方法是给用户调用的,如果你想判断2个对象是否相等,你可以重写equals方法,然后在代码中调用,就可以判断他们是否相等了。简单来讲,equals方法主要是用来判断从表面上看或者从内容上看,2个对象是不是相等。举个例子,有个学生类,属性只有姓名和性别,那么我们可以认为只要姓名和性别相等,那么就说这2个对象是相等的。hashcode方法一般用户不会去调用,比如在hashmap中,由于key是不可以重复的,他在判断key是不是重复的时候就判断了hashcode这个方法,如果hashCode相等,再比较equals,equals返回true则不存,返回false则存。这里不可以重复是说equals和hashcode只要有一个不等就可以了!所以简单来讲,hashcode相当于是一个对象的编码,就好像文件中的md5,他和equals不同就在于他返回的是int型的,比较起来不直观。我们一般在覆盖equals的同时也要覆盖hashcode,让他们的逻辑一致。举个例子,还是刚刚的例子,如果姓名和性别相等就算2个对象相等的话,那么hashcode的方法也要返回姓名的hashcode值加上性别的hashcode值,这样从逻辑上,他们就一致了。要从物理上判断2个对象是否相等,用==就可以了,如果两个对象的物理(内存)地址相等,那么这两个对象肯定就是同一个对象。

    • 什么是AOP?
      1.AOP概念介绍
        所谓AOP,即Aspect orientied program,就是面向方面(切面)的编程,是对面向对象的思维方式的有力补充。AOP的好处是可以动态地添加和删除在切面上的逻辑而不影响原来的执行代码
      2.解释什么是方面(切面)
        所谓方面(切面),指的是贯穿到系统的各个模块中的系统一个功能就是一个方面(切面),比如,记录日志,统一异常处理,事务处理,权限检查,这些功能都是软件系统的一个面,而不是一点,在各个模块中都要出现。
      3.什么是面向方面编程
        把系统的一个方面的功能封装成对象的形式来处理就是面向方面(切面)编程
      4.怎么进行面向方面编程
        把功能模块对应的对象作为切面嵌入到原来的各个系统模块中,采用代理技术,代理会调用目标,同时把切面功能的代码(对象)加入进来。所以,用spring配置代理对象时只要要配两个属性,分别表示目标和切面对象(Advisor)。

    • 谈谈你对mvc的理解
      MVC是Model—View—Controler的简称。即模型—视图—控制器。MVC是一种设计模式,它强制性的把应用程序的输入、处理和输出分开。
      MVC中的模型、视图、控制器它们分别担负着不同的任务。

    视图: 视图是用户看到并与之交互的界面。视图向用户显示相关的数据,并接受用户的输入。视图不进行任何业务逻辑处理。

    模型: 模型表示业务数据和业务处理。相当于JavaBean。一个模型能为多个视图提供数据(比如个人主页,自己模式和游客模式就是不同的视图)。这提高了应用程序的重用性

    控制器: 当用户单击Web页面中的提交按钮时,控制器接受请求并调用相应的模型去处理请求。然后根据处理的结果调用相应的视图来显示处理的结果。
    MVC的处理过程:首先控制器接受用户的请求,调用相应的模型来进行业务处理,并返回数据给控制器。控制器调用相应的视图来显示处理的结果。并通过视图呈现给用户。

    • 实现一个接口需要实现接口的所有方法吗
      看实现类是否是抽象类;如果不是抽象类,需要全部实现;如果是抽象类,就没有限制了(可以一个都不实现,可以部分实现,可以全部实现)

    相关文章

      网友评论

          本文标题:注意点

          本文链接:https://www.haomeiwen.com/subject/clbmrqtx.html