android面试(java)题目收集

1.Java 面向对象有哪些特征封装、继承、多态。
2.short s1=1;s1=s1+1 有什么错?short s1=1;s1+=1;有什么错?第一个是有错的,short 在内存中占 2 个字节,而整数 1 默认为 int 型占 4 个字节,s1+1 其实这个时候就向上转型为 int 类型了,因此第一行代码必须强转才行。第二个之所以可以是以为这句话翻译过来就是 s1++,也就是 short 类型的数据自身加增 1,因此不会有问题
3.静态成员类、非静态成员类有什么区别?什么是匿名内部类?静态成员类相当于外部类的静态成员,是外部类在加载的时候进行初始化,非静态成员类相当于外部类的普通成员,当外部类创建对象的时候才会初始化。匿名内部一般都是在方法里面直接通过 newClassName(){};形式的类。比如我们 new Thread(new Runnable(){}).start();就用到了匿名内部类。
4.abstract class 和 interface 有什么区别?前者是抽象类,可以有抽象方法,也可以没有。后者是接口,只能有抽象方法。他们都不能创建对象,需要被继承
5.ArrayList 是不是线程安全的?如果不是,如何是 ArrayList 成为线程安全的?不安全的。可以使用 Collections.synchronizedList(list)将 list 变为线程安全的。
6.以下两条语句返回值为 true 的有:A:“yiyaowang”==“yiyaowang”; B: “yiyaowang”.equals(new String(“yiyaowang”));第一个返回 true,都是字符串常量,存储在字符串常量池中,且只有一份。第二个返回 true,用equals 比较的是字符串内容。
7.当一个对象被当做参数传递到一个方法后,此方法可以改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?java 中只有值传递,没有引用传递。这里的引用本身就是值,传递的是引用这个值。
8.请描述下 JVM 加载 class 文件的原理机制JVM 加载 class 是动态性的,也就是当“需要”的时候才会加载,这是也是为节约 JVM 内存来考虑的。同时 JVM 的类加载是父类委托机制,这个机制简单来讲,就是“类装载器有载入类的需求时,会先请示其 Parent 使用其搜索路径帮忙载入,如果 Parent 找不到,那么才由自己依照自己的搜索路径搜索类”。
9.ArrayList、HashSet、HashMap 源码每个方法都没有加锁,显然都是线程不安全的

10.如何将一个 "java 对象"序列化到文件里
在 java 中能够被序列化的类必须先实现 Serializable 接口,该接口没有任何抽象方法只是起到一个标记作用。

//对象输出流
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new
FileOutputStream(new File("D://obj")));
objectOutputStream.writeObject(new User("zhangsan", 100));
objectOutputStream.close();
//对象输入流
ObjectInputStream objectInputStream = new ObjectInputStream(new
FileInputStream(new File("D://obj")));
User user = (User)objectInputStream.readObject();
System.out.println(user);
objectInputStream.close();
11.字符和字节底层设备永远只接受字节数据,有时候要写字符串到底层设备,需要将字符串转成字节再进行写入。字符流是字节流的包装,字符流则是直接接受字符串,它内部将串转成字节,再写入底层设备,这为我们向 IO 设别写入或读取字符串提供了一点点方便。字符向字节转换时,要注意编码的问题,因为字符串转成字节数组,其实是转成该字符的某种编码的字节形式,读取也是反之的道理。

12.HashMap 排序题

13.abstract class 和 interface 有什么区别?

含有 abstract 修饰符的 class 即为抽象类,abstract 类不能创建的实例对象。含有 abstract 方法的类必须
定义为 abstract class,abstract class 类中的方法不必是抽象的。abstract class 类中定义抽象方法必须在具体
(Concrete)子类中实现,所以,不能有抽象构造方法或抽象静态方法。如果的子类没有实现抽象父类中的所
有抽象方法,那么子类也必须定义为 abstract 类型。
接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定
义默认为 public abstract 类型,接口中的成员变量类型默认为 public static final。
下面比较一下两者的语法区别:
1.抽象类可以有构造方法,接口中不能有构造方法。
2.抽象类中可以有普通成员变量,接口中没有普通成员变量
3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方
法。
4. 抽象类中的抽象方法的访问类型可以是 public,protected 和(默认类型,虽然
eclipse 下不报错,但应该也不行),但接口中的抽象方法只能是 public 类型的,并且默认即为 public
abstract 类型。
5. 抽象类中可以包含静态方法,接口中不能包含静态方法
6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口
中定义的变量只能是 public static final 类型,并且默认即为 public static final 类型。
7. 一个类可以实现多个接口,但只能继承一个抽象类。
下面接着再说说两者在应用上的区别:
接口更多的是在系统架构设计方法发挥作用,主要用于定义模块之间的通信契约。而抽象类在代码实
现方面发挥作用,可以实现代码的重用,例如,模板方法设计模式是抽象类的一个典型应用,假设某个项
目的所有 Servlet 类都要用相同的方式进行权限判断、记录访问日志和处理异常,那么就可以定义一个抽象
的基类,让所有的 Servlet 都继承这个抽象基类,在抽象基类的 service 方法中完成权限判断、记录访问日
志和处理异常的代码,在各个子类中只是完成各自的业务逻辑代码,伪代码如下:
public abstract class BaseServlet extends HttpServlet{
public final void service(HttpServletRequest request, HttpServletResponse response) throws
IOExcetion,ServletException {
记录访问日志
进行权限判断
if(具有权限){
try{
doService(request,response);
}
catch(Excetpion e) {
记录异常信息
}
}
}
protected abstract void doService(HttpServletRequest request, HttpServletResponse response) throws
IOExcetion,ServletException;
//注意访问权限定义成 protected,显得既专业,又严谨,因为它是专门给子类用的
}
public class MyServlet1 extends BaseServlet
{
protected void doService(HttpServletRequest request, HttpServletResponse response) throws
IOExcetion,ServletException
{
本 Servlet 只处理的具体业务逻辑代码
}
}
父类方法中间的某段代码不确定,留给子类干,就用模板方法设计模式。
备注:这道题的思路是先从总体解释抽象类和接口的基本概念,然后再比较两者的语法细节,最后再
说两者的应用区别。比较两者语法细节区别的条理是:先从一个类中的构造方法、普通成员变量和方法(包
括抽象方法),静态变量和方法,继承性等 6 个方面逐一去比较回答,接着从第三者继承的角度的回答,特
别是最后用了一个典型的例子来展现自己深厚的技术功底。

14.ArrayList 和 Vector 的区别

ArrayList 与 Vector 底层都是基于数组的,因此它们的实现代码也大致相似。区别在于
Vector 是一个古老的集合,Vector 还有一个特征:它是线程安全的,因此性能比较差。而 ArrayList 并不是线程安
全的,因此性能较好。实际上即使需要在多线程环境下使用 List 集合,也应该选择 ArrayList,
而不是 Vector,因为 Java 还提供了一个 Collections 工具类,它可以把 ArrayList 包装成线程
安全的集合类,例如如下代码:
List list = Collections.synchronizedList(new ArrayList());

15.Java中实现线程阻塞的方法:

(1)线程睡眠:Thread.sleep (long millis)方法,使线程转到阻塞状态。millis参数设定睡眠的时间,以毫秒为单位。当睡眠结束后,就转为就绪(Runnable)状态。sleep()平台移植性好。

(2)线程等待:Object类中的wait()方法,导致当前的线程等待,直到其他线程调用此对象的 notify() 唤醒方法。这个两个唤醒方法也是Object类中的方法,行为等价于调用 wait() 一样。wait() 和 notify() 方法:两个方法配套使用,wait() 使得线程进入阻塞状态,它有两种形式,一种允许 指定以毫秒为单位的一段时间作为参数,另一种没有参数,前者当对应的 notify() 被调用或者超出指定时间时线程重新进入可执行状态,后者则必须对应的 notify() 被调用.

(3)线程礼让,Thread.yield() 方法,暂停当前正在执行的线程对象,把执行机会让给相同或者更高优先级的线程。yield() 使得线程放弃当前分得的 CPU 时间,但是不使线程阻塞,即线程仍处于可执行状态,随时可能再次分得 CPU 时间。调用 yield() 的效果等价于调度程序认为该线程已执行了足够的时间从而转到另一个线程.

(4)线程自闭,join()方法,等待其他线程终止。在当前线程中调用另一个线程的join()方法,则当前线程转入阻塞状态,直到另一个进程运行结束,当前线程再由阻塞转为就绪状态。

16.wait和sleep方法的区别?

wait和sleep方法的区别

List 和 map 的区别一个是存储单列数据的集合,另一个是存储键和值这样的双列数据的集合,List 中存储的数据是有顺序,并且允 许重复;Map 中存储的数据是没有顺序的,其键是不能重复的,它的值是可以有重复的。
HashMap(接口,非线程安全的)和 HashTable(线程按全) 有什么区别HashMap 是线程不安全的,HashMap 是一个接口,是 Map 的一个子接口,是将键映射到值得对象,不允许键值重复, 允许空键和空值;由于非线程安全,HashMap 的效率要较 HashTable 的效率高一些. HashTable 是线程安全的一个集合,不允许 null 值作为一个 key 值或者 Value 值; HashTable 是 sychronize,多个线程访问时不需要自己为它的方法实现同步,而 HashMap 在被多个线程访问的时 候需要自己为它的方法实现同步;

Java 中 ArrayList 和 Linkedlist 区别?

LinkedList 使用了循环双向链表数据结构。与基于数组的 ArrayList 相比,这是两种截然不同的实现技术,这也决 定了它们将适用于完全不同的工作场景。
在 JDK 的实现中,无论 LikedList 是否 为空,链表内部都有一个 header 表项,它既表示链表的开始,也表示链表的结尾。表项 header 的后驱表项便是链表中第一个元素,表项 header 的前驱表项便是链表中最后一个元素。
在这里插入图片描述

List a=new ArrayList()和 ArrayList a =new ArrayList()的区别?

List list = new ArrayList();这句创建了一个 ArrayList 的对象后把上溯到了 List。此时它是一个 List 对象了,有些 ArrayList 有但是 List 没有的属性和方法,它就不能再用了。而 ArrayList list=new ArrayList();创建一对象则保留了 ArrayList 的所有属性。 所以需要用到 ArrayList 独有的方法的时候不能用前者。

为什么要用 clone?

首先,克隆对象是很有必要的,当一个对象需要被多人操作,但是又不想相互影响,需要保持原对象的状态,这 时,就会克隆很多个相同的对象。

new 一个对象的过程和 clone 一个对象的过程区别

new 操作符的本意是分配内存。程序执行到 new 操作符时, 首先去看 new 操作符后面的类型,因为知道了类型, 才能知道要分配多大的内存空间。分配完内存之后,再调用构造函数,填充对象的各个域,这一步叫做对象的初始化, 构造方法返回后,一个对象创建完毕,可以把他的引用(地址)发布到外部,在外部就可以使用这个引用操纵这个对 象。
clone 在第一步是和 new 相似的, 都是分配内存,调用 clone 方法时,分配的内存和原对象(即调用 clone 方 法的对象)相同,然后再使用原对象中对应的各个域,填充新对象的域, 填充完成之后,clone 方法返回,一个新的 相同的对象被创建,同样可以把这个新对象的引用发布到外部.
复制对象和复制引用的区别

  1. Person p = new Person(23, “zhang”);
  2. Person p1 = p;
  3. System.out.println§;
  4. System.out.println(p1);
    当 Person p1 = p;执行之后, 是创建了一个新的对象吗?
    首先看打印结果:
    1.com.itheima.Person@2f9ee1ac
    2.com.itheima.Person@2f9ee1ac
    可以看出,打印的地址值是相同的,既然地址都是相同的,那么肯定是同一个对象。p 和 p1 只是引用而已,他们 都指向了一个相同的对象 Person(23, “zhang”) 。 可以把这种现象叫做引用的复制。上面代码执行完成之后, 内 存中的情景如下图所示:
    在这里插入图片描述

而下面的代码是真真正正的克隆了一个对象。
3.Person p = new Person(23, “zhang”);
4.Person p1 = (Person) p.clone();
5.System.out.println§; 6.System.out.println§;
在这里插入图片描述

深拷贝和浅拷贝(clone是浅拷贝的)在这里插入图片描述

1public class Person implements Cloneable{
2.private int age ;
3private String name; 
4public Person(int age, String name) { 
5this.age = age;
6this.name = name;
7}
8public Person() {} 
9public int getAge() { 
10return age; 
11} 
12public String getName() { 
13return name; 
14} 
15@Override 
16protected Object clone() throws CloneNotSupportedException { 
17return (Person)super.clone(); 
18} 
19}

深拷贝

1static class Body implements Cloneable{
2public Head head; 
3public Body() {}
4public Body(Head head) {this.head = head;}
5@Override 
6protected Object clone() throws CloneNotSupportedException { 
7. Body newBody = (Body) super.clone(); 
8. newBody.head = (Head) head.clone();
9return newBody; 
10} 
11}
12static class Head implements Cloneable{
13public Face face;
14public Head() {} 
15@Override 
16protected Object clone() throws CloneNotSupportedException { 
17return super.clone(); 
18} } 
19public static void main(String[] args) throws CloneNotSupportedException { 
20. Body body = new Body(new Head(new Face())); 
21. Body body1 = (Body) body.clone();
22. System.out.println("body == body1 : " + (body == body1) );
23. System.out.println("body.head == body1.head : " + (body.head == body1.head)); 
24}

synchronized 和 volatile 关键字的作用

一旦一个共享变量(类的成员变量、类的静态成员变量)被 volatile 修饰之后,那么就具备了两层语义:
1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是 立即可见的。 2)禁止进行指令重排序。 volatile 本质是在告诉 jvm 当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized 则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
1.volatile 仅能使用在变量级别;
synchronized 则可以使用在变量、方法、和类级别的
2.volatile 仅能实现变量的修改可见性,并不能保证原子性;
synchronized 则可以保证变量的修改可见性和原子性
3.volatile 不会造成线程的阻塞;
synchronized 可能会造成线程的阻塞。
4.volatile 标记的变量不会被编译器优化;
synchronized 标记的变量可以被编译器优化

请叙述一下您对线程池的理解

第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定 性,使用线程池可以进行统一的分配,调优和监控。

16.static Semaphore semaphore = new Semaphore(5,true);
17. public static void main(String[] args) { 
18. for(int i=0;i<100;i++){ 
19. 	new Thread(new Runnable() { 
20.  	@Override 
21. 	public void run() { 
22. 	test(); 
23.  	} 
24.  	}).start();
25. }
26. 
27. } 
30. public static void test(){ 
29. 	try { 
30. 	//申请一个请求 
31. 		semaphore.acquire(); 
32. 	} catch (InterruptedException e1) { 
33. 		e1.printStackTrace(); 
34. 	} 
35. System.out.println(Thread.currentThread().getName()+"进来了"); 
36. 	try {
37. 		Thread.sleep(1000); 
38. 	} catch (InterruptedException e) { 
39. 		e.printStackTrace(); 
40. 	}
43. 	System.out.println(Thread.currentThread().getName()+"走了"); 
44. 	//释放一个请求
45. 	semaphore.release(); 
46. 	} 
47. }

三个线程 a、b、c 并发运行,b,c 需要 a 线程的数据怎么实现

一是使用纯 Java API 的 Semaphore 类来控制线程的等待和释放.

private static Semaphore semaphore = new Semaphore(0);

//通过该语句可以使semaphore +2
semaphore.release(2);

二是使 用 Android 提供的 Handler 消息机制

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值