牛客网(题目的回答大多数来自他人见解,少部分个人领悟)

来源:互联网 发布:js读取excel 编辑:程序博客网 时间:2024/05/29 19:42

2017.11.4

1.一个文件中的字符要写到另一个文件中,首先需要( )


使用标准输出流System.out.println()。
建立文件字符输出流。
建立文件字符输入流。
标准输入流System.in.read()。
网友回答的:一个文件中的字符要写到另一个文件中,首先要读出来,然而对计算机而言,input就是读进来(外面送进来),out就是写出去(里面往外面写),一个文件写到另外一个文件,所以我们需要先读取这个文件,也就是建立字符输入流。

package com.te;import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.io.Reader;public class InPutcopy {public static void main(String[] args) throws IOException {// TODO Auto-generated method stubFile file=new File("C:\\Users\\绝影\\Desktop\\桌面.txt");//创建一个新的file实例//读出对应输入流InputStream input = null;OutputStream out = null;InputStreamReader inp=null;OutputStreamWriter inp1=null;BufferedReader reader=null;BufferedWriter write=null;try {input = new FileInputStream(file);FileReader filer=new FileReader(file);inp=new InputStreamReader(input);//字节流字符流转化的桥梁 reader = new BufferedReader(filer);//缓冲读取字符 将字节流封装成BufferedReader对象File fi=new File("C:\\Users\\绝影\\Desktop\\7777.txt");//写入对应输出流out=new FileOutputStream(fi);//建立文件字节输出流FileWriter filer1=null;try {filer1 = new FileWriter(fi);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} inp1=new OutputStreamWriter(out);//字节流字符流转化的桥梁 write=new BufferedWriter(filer1);//缓冲写入字符 将字节流封装成BufferedReader对象char a[]=new char[21];byte b[]=new byte[21];input.read(b);//放入字节数组  //字节数组的read方法的源码,下面可知input.read(b)不会导致数组越界,就是担心文件内容放不了进入数组的情况,因为这个read方法本身//数组放入多少是已经固定的,并非将文件内容一下子全部放入,所以不会有越界情况/*public int read(byte b[]) throws IOException {          return read(b, 0, b.length);      }            *      */reader.read(a);//放入字符数组,同理不会因为文件里面的字符大于数组长度越界String line="";while((line=reader.readLine()) != null){//一个文件内容读入到另外一个//write.write(line);write.write(line);   //使用缓冲区中的方法将数据写入到缓冲区中。  //write.flush(); 如何finally中没有关闭流这里没有这一句会造成文件没有写入System.out.println(line);//这里也只是输出后半句}for(int i=0;i<21;i++) {System.out.println(b[i]);//48---57System.out.println(a[i]);//这里不懂,BufferedReader中的参数换inp前面的部分字符没有输出}} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally {reader.close();write.close();//这里把输出流关闭也会和write.flush()一样的效果,有点类似数据库的事务提交}        }}


2.以下多线程对int型变量x的操作,哪个不需要进行同步()

++x
x=y
x++
x=1

ABC不是原子性操作,例如想x++,先获取x的值,自增一,然后再把值赋给x,三步,中间任何一步执行时都可能被其他线程访问或者修改。所以需要同步。

package com.te;public class Multiplythread extends Thread{static int i=0;//多线程调用static int j=0;@Overridepublic  void run() {System.out.println(this);++i;}public  void runn() {++j;}public static void main(String[] args) {// TODO Auto-generated method stubfor(int i=0;i<1000;i++) {Multiplythread th=new Multiplythread();//线程1    th.start();    th.runn();   // System.out.println(i);}/* * 输出结果不确定(因为对于++i这一步不是原子操作,实际上分为了三步,每个java线程都有一份自己的工作内存,线程访问变量的时候,不能直接访问主内存中的变量,而是先把主内存的变量复制到自己的工作内存,然后操作自己工作内存里的变量,最后再同步给主内存。现在就可以解释为什么5个线程执行a++最后结果不一定是5了,因为a++可以分解为3步操作:1.把主内存里的a复制到线程的工作内存2.线程对工作内存里的a执行a=a+13.把线程工作内存里的a同步回主内存,由于在这过程中线程是同步的,没有先后执行顺序),这里需要上面线程多一点效果才明显*///我们理想输出的是1000,但是会出现不同结果.因为假设线程1先运行,当它执行完1,2时,到第二个线程开始跑,第二个线程成功执行完1,2,3然后线程1获得cpu,继续执行第三把自己工作内存里的变量,再同步给主内存//同步过去i的值是1,而线程2执行同步的值也是1,此时类变量i就是1,而不是我们想要的结果2System.out.println("我是来看看终极i的值是:"+Multiplythread.i);//不受线程控制的变量j就是输出1000System.out.println("我是来看看终极j的值是:"+Multiplythread.j);}}

3.关于匿名内部类叙述正确的是? ( )


正确答案: B   你的答案: A (错误)

匿名内部类可以继承一个基类,不可以实现一个接口
匿名内部类不可以定义构造器
匿名内部类不能用于形参
以上说法都不正确
网友答案:
匿名内部类的创建格式为: new 父类构造器(参数列表)|实现接口(){
                                             //匿名内部类的类体实现
                                        }
  1. 使用匿名内部类时,必须继承一个类或实现一个接口
  2. 匿名内部类由于没有名字,因此不能定义构造函数
  3. 匿名内部类中不能含有静态成员变量和静态方法

A.构造函数可以省略,省略构造函数则new对象实例时,所有的数据类型赋值为0,bool类型赋值为FALSE,引用类型赋值为NULL。
B.构造函数必须与类同名,而且不能有返回类型。而方法是可以与类同名的,但是必须声明返回数据类型。
C.正确,当new对象是首先调用静态初始数据块(可省略),然后调用父类构造函数(不是子类则不调用),最后调用自己的构造函数(一定调用),这样才能生成一个对象的实例。
D.构造函数是可以重载的,重载的要求是参数不同。

4.下面不是面向对象的基本原则的是?

正确答案: C   你的答案: E (错误)

单一职责原则(Single-Resposibility Principle)
开放封闭原则(Open-Closed principle)
抽象类原则(Abstract-Class principle)
依赖倒置原则(Dependecy-Inversion Principle)
接口隔离原则(Interface-Segregation Principle)

s( Single-Resposibility Principle ): 单一职责原则
o( Open-Closed principle ): 开放封闭原则
l( Liskov-Substituion Principle ): 里氏原则
i( Interface-Segregation Principle ): 接口隔离原则
d( Dependecy-Inversion Principle ): 依赖倒置原则
一个单词:立方体(solid),很好记!!!

单一职责原则(Single-Resposibility Principle):一个类,最好只做一件事,只有一个引起它的变化。单一职责原则可以看做是低耦合、高内聚在面向对象原则上的引申,将职责定义为引起变化的原因,以提高内聚性来减少引起变化的原因。 
开放封闭原则(Open-Closed principle):软件实体应该是可扩展的,而不可修改的。也就是,对扩展开放,对修改封闭的。 
Liskov替换原则(Liskov-Substituion Principle):子类必须能够替换其基类。这一思想体现为对继承机制的约束规范,只有子类能够替换基类时,才能保证系统在运行期内识别子类,这是保证继承复用的基础。 
依赖倒置原则(Dependecy-Inversion Principle):依赖于抽象。具体而言就是高层模块不依赖于底层模块,二者都同依赖于抽象;抽象不依赖于具体,具体依赖于抽象。 
接口隔离原则(Interface-Segregation Principle):使用多个小的专门的接口,而不要使用一个大的总接口


下列哪个说法是正确的()

正确答案: D   你的答案: B (错误)

ConcurrentHashMap使用synchronized关键字保证线程安全
HashMap实现了Collction接口
Array.asList方法返回java.util.ArrayList对象
SimpleDateFormat是线程不安全的


A选项中,ConcurrentHashMap 使用segment来分段和管理锁,segment继承自ReentrantLock,因此ConcurrentHashMap使用ReentrantLock来保证线程安全。

B中,HashMap定义规则如下:

public class HashMap<K,V>    extends AbstractMap<K,V>    implements Map<K,V>, Cloneable, Serializable
C中,应该是Arrays.asList(),其将一个数组转化为一个List对象,这个方法会返回一个ArrayList类型的对象, 这个ArrayList类并非java.util.ArrayList类,而是Arrays类的内部类: 
A、ConcurrentHashMap实际上时 HashTable的升级版,使用segment来分段和管理锁,并不是synchronized;
B、 HashMap实现的接口有:Serializable, Cloneable, Map<K,V> ,没有实现Cllectio
C、Arrays.asList()方法返回的列表是Arrays.ArrayList类型的,并不是java.util.ArrayList;


JAVA反射机制主要提供了以下哪些功能?

正确答案: A B C D   你的答案: A B C (错误)

在运行时判断一个对象所属的类
在运行时构造一个类的对象
在运行时判断一个类所具有的成员变量和方法
在运行时调用一个对象的方法
普通的java对象是通过new关键字把对应类的字节码文件加载到内存,然后创建该对象的。
反射是通过一个名为Class的特殊类,用Class.forName("className");得到类的字节码对象,然后用newInstance()方法在虚拟机内部构造这个对象(针对无参构造函数)。
也就是说反射机制让我们可以先拿到java类对应的字节码对象,然后动态的进行任何可能的操作,
包括
  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时调用任意一个对象的方法
这些都是反射的功能。
使用反射的主要作用是方便程序的扩展。



关于ThreadLocal 以下说法正确的是

正确答案: D E   你的答案: A B C E (错误)

ThreadLocal继承自Thread
ThreadLocal实现了Runnable接口
ThreadLocal重要作用在于多线程间的数据共享
ThreadLocal是采用哈希表的方式来为每个线程都提供一个变量的副本
ThreadLocal保证各个线程间数据安全,每个线程的数据不会被另外线程访问和破坏
1、ThreadLocal的类声明:
public class ThreadLocal<T>
可以看出ThreadLocal并没有继承自Thread,也没有实现Runnable接口。所以AB都不对。
2、ThreadLocal类为每一个线程都维护了自己独有的变量拷贝。每个线程都拥有了自己独立的一个变量。
所以ThreadLocal重要作用并不在于多线程间的数据共享,而是数据的独立,C选项错。
由于每个线程在访问该变量时,读取和修改的,都是自己独有的那一份变量拷贝,不会被其他线程访问,
变量被彻底封闭在每个访问的线程中。所以E对。
3、ThreadLocal中定义了一个哈希表用于为每个线程都提供一个变量的副本:
 static class ThreadLocalMap {

        static class Entry extends WeakReference<ThreadLocal> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal k, Object v) {
                super(k);
                value = v;
            }
        }

        /**
         * The table, resized as necessary.
         * table.length MUST always be a power of two.
         */
        private Entry[] table;
}