Android学习笔记六:Java基础知识

2018-03-24 12:05 评论 0 条

摘要:

最近在整理Android岗位面试题答案,虽然工作已有两年,独立开发了好几个APP,但在不查资料的情况下,回答这些试题非常的困难,瞬间感觉一万点伤害。即使不为了找工作,整理这样一份Android面试题答案,也可以加深对各个知识点的理解,这一整套面试题基于《最全的BAT大厂面试题整理》,然后将每一个分类拆分成附带参考答案的独立的文章,在此非常感谢整理试题的原作者。

Android学习笔记六:Java基础知识

Android学习笔记七:Java源码深入学习(25号更新)

Android学习笔记八:Java常用数据结构(26号更新)

Android学习笔记九:Java线程、多线程和线程池(27号更新)

Note that:文章中给出的答案尽管参考了网上的很多资料,但肯定回答得还不够到位,更需要在实际的环境中运用、验证(求内推哈)

  • Java基本数据类型及各自所占的字节数
类型 字节
byte 1个字节
short 2个字节
int 4个字节
long 8个字节
float 2个字节
double 4个字节
chart 2个字节
boolean 视具体编译环境而定
  • java中==和equals和hashCode的区别

两个基本数据类型使用==,比较的是两个变量值;两个对象使用==,比较的是两个对象的内存地址

使用类继承自Object基类,Object类定义了equals()方法和hasCode()方法,前者的实现调用==进行比较,开发者通过重写这两个方法实现自定义比较的逻辑。

重写equals()方法,必须重写hasCode()方法,两个数值或对象通过equal比较返回true,那么这两个数值或对象的hasCode值一样;反之,两个数值或对象的hasCode值一样,两个数值或对象的equal不一定为true

Java中==和equals的区别,equals和hashCode的区别

  • int与integer的区别

int,是一种基本的数据类型,存储的是一个数值,默认值0;integer是一个int的封装类,实例化一个内存地址赋值给一个变量,才可以使用,默认值null

  • 探探对java多态的理解

多态是面向对象编程思想的三个基本特征之一,指的是一种动态绑定,在执行期间判断引用对象的实际类型,调用其对应的属性或方法。

作用:消除类型之间的耦合关系

浅谈对java多态的理解

  • String、StringBuffer、StringBuilder区别

String对象一定被创建,它是不可更改的,编程中看到的同一变量名的String对象,重新赋值的过程实际也是重新创建对象的过程,同时JVM回收了“旧对象”,重复的创建和回收,造成String执行缓慢

StringBuilder和StringBuffer对变量重复赋值或改变保留值,不用重复创建和回收对象,执行速度相比会快一些(除一些特殊情况)

StringBuffer的方法用sychronized关键字修饰,适合多线程环境下使用,是线程安全的

StringBuilder的方法没有sychronized关键字修饰,不保证同步操作,适合单线程环境下使用,速度会比StringBuffer快

Java中的String,StringBuilder,StringBuffer三者的区别

  • 什么是内部类?内部类的作用

内部类,指的是定义在一个类里面的类,分为静态内部类(static修饰的类)、非静态内部类(也叫成员内部类)、方法内部类和匿名内部类,包装内部类的类称为外部类

作用:
内部类提供更好的封装,把内部类隐藏在外部类里面,不允许同一包名的其它类访问该类

保护内部类的隐私数据

  • 抽象类和接口区别

抽象类和接口不能直接实例化,抽象类的变量指向实现抽象方法的子类对象,接口的变量指向接口的实现类对象。

抽象类是单一继承,接口可以有多个实现

接口定义的变量只能是公共的静态的常量,抽象类的变量是普通的变量

接口定义的方法只能是公共的抽象的方法,抽象类的方法可以是抽象的方法或非抽象的方法

抽象方法只能被声明,不能实现,接口是设计的结果,抽象类是重构的结果

抽象方法要被实现,所以不能是静态的,也不能是私有的

接口和抽象类有什么区别

  • 抽象类的意义

抽象类的意义,要依赖抽象,不要依赖具体类,根据多态的特性,在执行期间判断引用对象的类型,调用对应的属性和方法

  • 抽象类与接口的应用场景

在一个继承关系的类中,将同一行为的不同表现提取为抽象的方法,将父类声明为抽象类,应用的场景有:BaseActivity、BaseFragment、BaseAdapter、ViewHolder等基类中

接口应用的场景有:BaseAdapter子类监听item单击事件

  • 抽象类是否可以没有方法和属性?

抽象类可以没有方法和属性,使用abstract关键字修饰

  • 接口的意义

接口的意义,针对接口编程,不针对实现编程,好处是可以有多个实现类,解耦程序,方便修改、维护。

  • 泛型中extends和super的区别

泛型类<? extends T>表示以T为上界的一组子类,适合读取数据,不建议调用写入数据的方法,否则编译器会报错;泛型<? super T>表示以T为下界的一组超类,适合调用写入数据的方法,不适合读取数据。

Android开发之深入理解泛型extends和super的区别

  • 父类的静态方法能否被子类重写

父类的静态方法可以被子类继承,但不能被重写(即使子类重写了父类的静态方法,最终调用的仍然是父类的静态方法)

原因:static修饰的方法,在代码编译时分配了一块内存地址,该内存地址只当程序退出时才会被回收,调用该方法的指针都指向该地址

子类能否重写父类的静态方法

  • 进程和线程的区别

进程是分配资源(CPU、内存)的最小单位,线程是程序执行的最小单位

一个进程可以包含多个线程,线程共享整个进程中的资源(CPU、内存),一个进程至少包含一个线程

线程执行开销小,但不利于资源的管理和保护;而进程正相反

线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据;进程间的通信要以通信的方式(IPC)进行

一道面试题:说说进程和线程的区别

进程和线程的区别

进程和线程的区别和联系

  • 序列化的方式

常用的序列化的方式有:实现Serializable接口、实现Externalizable接口、实现Parcelable接口

另外两种不常用的方式:gson、Google protobuf

Java序列化的几种方式

  • Serializable 和Parcelable 的区别

Serializable是Java提供的序列化的方式,使用起来简单但是开销大,序列化和反序列化需要进行大量的I/O操作;

Parcelable是android API增加的序列化的方式,缺点是使用起来稍微麻烦点,但是效率较高。

  • 静态属性和静态方法是否可以被继承?是否可以被重写?以及原因?

静态属性和静态方法可以被子类继承,但不可以被重写(即使被子类重写,最终调用的仍然是父类的静态属性和静态方法)

原因:static修饰的属性和方法,在代码编译期就分配了独立的内存地址,即使子类重写了父类的静态方法,变量指向的还是编译器已分配的内存地址。

  • 静态内部类的设计意图

静态内部类实现的效果和独立声明一个类的效果一样,不同之处是静态内部类封装在一个类里

将只想给外部类使用的类声明成静态内部类,可以实现更好的隐藏,不允许除外部类以外的类使用

同时,静态内部类可以通过外部类名区别,可以在不同的类中声明名字一样的静态内部类,比如:Builder

  • 成员内部类、静态内部类、局部内部类和匿名内部类的理解,以及项目中的应用

成员内部类,作为外部类的一个成员,可以直接访问外部类的所有属性和方法(包括private属性和方法),成员内部类不允许声明static的变量和方法

应用:一个Activity中,可以声明一个ViewPager的成员内部类,直接使用外部类的数据集

静态内部类,没持有一个指向外部类的引用,不可以使用外部类非static的属性和方法

应用:在使用Builder设计模式的时候,经常需要将内部类设计成static

局部内部类,嵌套在方法作用域内或代码块内,只对该方法的局部变量是可见的

应用:在一个方法里,需要进行复杂的处理过程,将处理的过程使用一个局部内部类封装

匿名内部类,没有访问修饰符,new关键字实现一个接口或继承一个父类(抽象类),重写接口或父类里面的抽象方法,匿名内部类使用一次就被GC回收了

应用:在BaseAdapter的getView方法中,给每一个item添加一个点击的事件

Java的四种内部类

  • 谈谈对kotlin的理解

kotlin作为一门新生代的语言,成为当前微信公众号、社区讨论最热门的开发语言之一,有望成为代替Java的Android开发语言。

原因有:

Google主推kotlin作为Android开发的一级语言

IDE支持可以将Java代码一键转成kotlin代码,对Java完美兼容

kotlin编码的大幅度精简、封装大量的函数库、各种语法糖,有效提高了Android的开发效率

如何评价 Kotlin 语言?

  • 闭包和局部内部类的区别

可以把闭包理解成编程的一种方式,把“包装”在一个类中的类或“包装”在一个方法中的类称为一个闭包

局部内部类是“包装”在一个方法中的类,可以说局部内部类是一个闭包,它的作用是可以在闭包作用域外访问闭包内的方法和属性

按照上述的定义,成员内部类也可以称为一个闭包

public interface IEngineer {
    public void work();
}
public abstract class People {
    public abstract void work();
    public abstract IEngineer getEngineer();
}
public class Teacher extends People {
    IEngineer engineer;

    @Override
    public void work() {
        System.out.println("I am a teachcer !");

    }

    @Override
    public IEngineer getEngineer() {

        return engineer;
    }

    public void setEngineer(IEngineer engineer) {
        this.engineer = engineer;
    }
}
    public static void main(String[] args) {
        Teacher teachcer = new Teacher();
        teachcer.setEngineer(new IEngineer() {

            @Override
            public void work() {
                System.out.println("I am a English Teacher");
            }
        });
        teachcer.work();
        //如何访问一个局部内部类的work()方法?
        teachcer.getEngineer().work();
    }

学习Javascript闭包(Closure)

什么是闭包?闭包的优缺点?

为什么说Java匿名内部类是残缺的闭包

java内部类与内部类的闭包和回调

Java语法糖系列五:内部类和闭包

  • String 转换成 Integer的方式及原理

第一种方式:构造函数

Integer integer=new Integer(str);
System.out.println(integer);

第二种方式:parseInt(String,int)

//parseInt(String,int)将一个字符串转换成基本数据类型int
int value=Integer.parseInt(str);
Integer integer=new Integer(value);//装箱操作
System.out.println(integer);

第三种方式:valueOf(String,int)

//valueOf(String,int)将一个字符串转换成对象Integer
Integer integer=Integer.valueOf(str);
System.out.println(integer);

原理分析:

查看Integer源码,发现将String转换成Integer的过程,先将String转换成基本数据类型int,再通过Integer的装箱操作将int转化成对象,所以上述三种方式最终调用下面两个方法:

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

将String转换成基本数据类型源码,逐个识别每个字符

public static Integer valueOf(String s, int radix) throws NumberFormatException {
        return Integer.valueOf(parseInt(s,radix));
    }
public static int parseInt(String s, int radix)throws NumberFormatException
    {
    ...

            multmin = limit / radix;
            while (i < len) {
                // Accumulating negatively avoids surprises near MAX_VALUE
                digit = Character.digit(s.charAt(i++),radix);
                if (digit < 0) {
                    throw NumberFormatException.forInputString(s);
                }
                if (result < multmin) {
                    throw NumberFormatException.forInputString(s);
                }
                result *= radix;
                if (result < limit + digit) {
                    throw NumberFormatException.forInputString(s);
                }
                result -= digit;
            }
        } else {
            throw NumberFormatException.forInputString(s);
        }
        return negative ? result : -result;
    }

参考资料:《最全的BAT大厂面试题整理

当前文章价值7.93元,扫一扫支付后添加微信提供帮助!(如不能解决您的问题,可以申请退款)

你可能感兴趣的文章

来源:每日教程每日一例,深入学习实用技术教程,关注公众号TeachCourse
转载请注明出处: https://www.teachcourse.cn/2602.html ,谢谢支持!

资源分享

IntentService,你了解的多少? IntentService,你了解的多少?
Android开发Service BroadcastReceiver Handler获取当前位置 Android开发Service Broadcas
HashMap方法解析 HashMap方法解析
浅谈SAX 浅谈SAX