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

本文深入探讨了Java编程中的关键知识点,包括文件操作流程、多线程处理、匿名内部类使用、面向对象基本原则等核心概念,并解析了ConcurrentHashMap、SimpleDateFormat等类的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 stub
		
		File 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 block
				e.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---57
				System.out.println(a[i]);//这里不懂,BufferedReader中的参数换inp前面的部分字符没有输出
			}
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.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;
	
	@Override
	public  void run() {
		System.out.println(this);
		++i;	
	}
	
	public  void runn() {
		++j;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		for(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+1
		3.把线程工作内存里的a同步回主内存,由于在这过程中线程是同步的,没有先后执行顺序),这里需要上面线程多一点效果才明显
		*/
		//我们理想输出的是1000,但是会出现不同结果.因为假设线程1先运行,当它执行完1,2时,到第二个线程开始跑,第二个线程成功执行完1,2,3然后线程1获得cpu,继续执行第三把自己工作内存里的变量,再同步给主内存
		//同步过去i的值是1,而线程2执行同步的值也是1,此时类变量i就是1,而不是我们想要的结果2
		System.out.println("我是来看看终极i的值是:"+Multiplythread.i);
		//不受线程控制的变量j就是输出1000
		System.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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值