后台开发面试题(.net与java)

最近面试了几家公司,发现大部分公司面试题有相似的地方。现在此记录下我还记得的一些题:

JAVA部分:

1.Java Map 按Key排序和按Value排序:

参考链接:Java Map 按Key排序和按Value排序

2.从一个文件中统计每个单词的次数,排序输出:

package com.test.string;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * java实现读取英文文章,统计其中每个单词出现的次数并输出
 * @author halbert
 *
 */
public class FileWordCount {
    
    public void count() throws IOException{
        BufferedReader reader = new BufferedReader(new FileReader("D:\test\english.txt"));
        StringBuffer buffer = new StringBuffer();
        String line = null;
        while( (line = reader.readLine()) != null ){
            buffer.append(line);
        }
        reader.close();
        Pattern expression = Pattern.compile("[a-zA-Z]+");    //定义正则表达式匹配单词
        String string = buffer.toString();
        Matcher matcher = expression.matcher(string);
        Map<string integer=""> map = new TreeMap<string integer="">();
        String word = "";
        int n = 0;
        Integer times = 0;
        while(matcher.find()){        //是否匹配单词
            word = matcher.group();        //得到一个单词,树映射中的键
            n++;
            if( map.containsKey(word) ){    //如果该键存在,则表示单词出现过
                times = map.get(word);        //得到单词出现的次数
                map.put(word, times+1);
            } else {
                map.put(word, 1);    //否则单词是第一次出现,直接放入map
            }
        }
        List<Map.Entry<string integer="">> list = new ArrayList<Map.Entry<string integer="">>(map.entrySet());
        Comparator<Map.Entry<string integer="">> comparator = new Comparator<Map.Entry<string integer="">>(){

            @Override
            public int compare(Entry<string integer=""> left, Entry<string integer=""> right) {
                return (left.getValue()).compareTo(right.getValue());
            }
            
        };
        Collections.sort(list, comparator);
        System.out.println("统计分析如下:");
        System.out.println("t 文章中单词总数" + n + "个");
        System.out.println("具体的信息在原文件目录的result.txt文件中");
        BufferedWriter bufw = new BufferedWriter(new FileWriter("D:\test\result.txt"));
        for(Entry<string integer=""> me : list){
            bufw.write(me+"");
            bufw.newLine();
        }
        bufw.write("english.txt中的单词总数" + n + "个");
        bufw.newLine();
        bufw.write("english.txt中不同单词" + map.size() + "个");
        bufw.close();
    }

    
    public static void main(String[] args) {
        try {
            FileWordCount fwc = new FileWordCount();
            fwc.count();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}
View Code

参考链接:java程序员的从0到1:统计某字符串在某文件中出现的次数(面试题)

3.手写arraylist:

参考链接:java面试题答疑(手写arraylist、进制转换、多线程、动态代理)

4.手写一把可重入锁:

public class MyLock implements Lock {

    private boolean isLocked = false; //定义一个变量,标记锁是否被使用

    private Thread runningThread = null; //第一次线程进来的时候,正在运行的线程为null

    private int count = 0;  //计数器

    @Override
    public synchronized void lock() {
        Thread currentThread = Thread.currentThread();
        //不断的重复判断,isLocked是否被使用,如果已经被占用,则让新进来想尝试获取锁的线程等待,直到被正在运行的线程唤醒
        //除了判断当前锁是否被占用之外,还要判断正在占用该锁的是不是本线程自己
        while(isLocked && currentThread != runningThread) { //如果锁已经被占用,而占用者又是自己,则不进入while循环
            try {
                wait();
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //进入该代码块有三种情况:
        // 1.第一个线程进来,此时isLocked变量的值为false,线程没有进入while循环体里面
        // 2.线程进入那个循环体里面,调用了wait()方法并经历了等待阶段,现在已经被另一个线程唤醒,
        // 3.线程不是第一次进来,但是新进来的线程就是正在运行的线程,则直接来到这个代码块
        // 唤醒它的线程将那个变量isLocked设置为true,该线程才跳出了while循环体

        //跳出while循环体,本线程做的第一件事就是赶紧占用线程,并告诉其他线程说:嘿,哥们,我占用了,你必须等待,计数器+1,并设置runningThread的值
        isLocked = true; //将isLocked变量设置为true,表示本线程已经占用
        runningThread = currentThread; //给正在运行的线程变量赋值
        count++; //计数器自增
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

    @Override
    public boolean tryLock() {
        return false;
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return false;
    }

    @Override
    public synchronized void unlock() {
        //线程释放锁,释放锁的过程分为三步
        //1. 判断发出释放锁的请求是否是当前线程
        //2. 判断计数器是否归零,也就是说,判断本线程自己进来了多少次,是不是全释放锁了
        //3. 还原标志变量
        if(runningThread == Thread.currentThread()) {
            count--;//计数器自减
            if(count == 0) { //判断是否归零
                isLocked = false; //将锁的状态标志为未占用
                runningThread = null;  //既然已经真正释放了锁,正在运行的线程则为null
                notifyAll(); //通知所有等待的线程,谁抢到我不管
            }
        }
    }

    @Override
    public Condition newCondition() {
        return null;
    }
}
--------------------- 
作者:SpringChang 
来源:CSDN 
原文:https://blog.csdn.net/zhang5476499/article/details/83794711 
版权声明:本文为博主原创文章,转载请附上博文链接!
View Code

参考链接:Java并发编程:自己动手写一把可重入锁

5.说几个JAVA中的单例模式,然后你最喜欢用哪个?为什么?

饿汉式和懒汉式。

//第一种形式: 饿汉式单例类
//饿汉式单例类.在类初始化时,已经自行实例化 
public class Singleton {
     private Singleton(){}
   private static Singleton instance = new Singleton(); 
   public static Singleton getInstance() {
     return instance;   
   } 
} 
//第二种形式:懒汉式单例类 
public class Singleton { 
    private Singleton(){}
  private static Singleton instance = null;
  public static synchronized Singleton getInstance() {
   if (instance==null)instance=new Singleton();
    return instance;
    }


} 
View Code

第一种形式要更加安全些
instance = new Singleton(); 
static属于类的资源,类资源在jvm加载类的时候就加载好了,instance一直引用这new Singleton(),所以永远都不会释放一直存在与内存中直到程序结束运行;
第2种的话如果两个线程同一时刻去访问getInstance的时候就可能创建两个实例,所以不安全;
解决办法(加上同步锁)。

参考链接:快速理解Java中的五种单例模式

6.说说你对Java中的栈内存和堆内存的看法:

参考链接:JAVA面试、进阶必备——堆内存与栈内存

7.http在传输时是无状态的,你是如何解决的:

可以使用Cookie来解决无状态的问题,Cookie就相当于一个通行证,第一次访问的时候给客户端发送一个Cookie,当客户端再次来的时候,拿着Cookie(通行证),那么服务器就知道这个是”老用户“。

参考链接:Java面试之http知识点(必问)    HTTP面试题都在这里

8.设计一个秒杀系统

参考链接:如何设计一个秒杀系统   秒杀系统设计(JAVA)

9.设计一个大数据高并发系统

秒杀系统和高并发系统均有视频,百度云链接:

链接: https://pan.baidu.com/s/1ooQaputdmsoHm9qT-PyXRw 提取码: 686e 
View Code

.NET部分:

其实C#和Java中大部分语法类似,故就算只想走Java部分题也有参考价值。

1.面向对象的三个特性,请简述。

封装:将对象中的方法,属性隐藏起来。外届程序调用对象的方法,只能通过对象提供给外部的接口来调用。这样可以可以让人忽略代码的具体细节实现,使代码更易维护。同时因为不能直接调用、修改对象内部的私有属性,在一定程度上保证了系统安全性。
继承:
主要用于代码复用,将多次使用的公共代码提取出来,以达到提高编码效率目的。
多态:
所谓的多态是指在继承体系中,所有派生类都从基类继承接口,但由于每个派生类都是独立的实体,因此在接收同一消息的时候,可能会生成不同的响应。多态的作用作为隐藏代码实现细节,使得代码能够模块化;扩展代码模块,实现接口重用。

2.用.net做B/S结构的系统,您是用几层结构来开发,每一层之间的关系以及为什么要这样分层?

三层。从下至上分别为:数据访问层、业务逻辑层(又或成为领域层)、表示层; 

数据访问层:有时候也称为是持久层,其功能主要是负责数据库的增删查改操作;

业务逻辑层:是整个系统的核心,它与这个系统的业务(领域)有关 

表示层:是系统的UI部分,负责使用者与整个系统的交互。  

优点:  分工明确,条理清晰,易于调试,而且具有可扩展性。 

缺点:  增加成本。

3.列举ASP.NET 页面之间传递值的几种方式。 

有页面传值、存储对象传值、ajax、类、model、表单等。但是一般来说,常用的较简单有QueryString,Session,Cookies,Application,Server.Transfer。

QueryString  传递一个或多个安全性要求不高或是结构简单的数值。但是对于传递数组或对象的话,就不能用这个方法了 

session(viewstate) 简单,但易丢失 作用于用户个人,过量的存储会导致服务器内存资源的耗尽。  

application 对象的作用范围是整个全局,也就是说对所有用户都有效。其常用的方法用Lock和UnLock 

cookie 简单,但可能不支持,可能被伪造 Cookie是存放在客户端的,而session是存放在服务器端的。而且Cookie的使用要配合ASP.NET内置对象Request来使用  input ttype="hidden" 简单,可能被伪造  url参数简单,显示于地址栏,长度有限

Server.Transfer  把流程从当前页面引导到另一个页面中,新的页面使用前一个页面的应答流  数据库稳定,安全,但性能相对弱

   参考链接:ASP.NET页面之间传递值的几种方式

4.事件和委托的区别

事件是委托的封装,可以理解为一种特殊的委托。

事件里面其实就两个方法(即add_event()和remove_event())和一个私有的委托变量,这两个方法里面分别是对这个私有的委托变量进行的合并和移除,当调用事件的+=时其实是调用的事件里面的add_event()方法,同样-=调用的是remove_event()方法。

事件只能够从对象外部增加新的响应方法和删除已知的响应方法,而不能主动去触发事件和获取其他注册的响应方法等信息。如果使用公有的delegate则不能做这些限制,也就是说事件对委托做了限制,使委托使用起来更加方便。也有人说事件是对委托的阉割,大概也是这个意思。

5.C#中的接口和类有什么异同

异: 
不能直接实例化接口。 
接口不包含方法的实现。 
接口、类和结构可从多个接口继承。但是C# 只支持单继承:类只能从一个基类继承实现。 
类定义可在不同的源文件之间进行拆分。 
同: 
接口、类和结构可从多个接口继承。 
接口类似于抽象基类:继承接口的任何非抽象类型都必须实现接口的所有成员。 
接口可以包含事件、索引器、方法和属性。 
一个类可以实现多个接口。

6.SQL注入是什么意思以及防止SQL注入:

参考链接:sql注入是什么意思以及防止sql注入?

SQL:

1. 取出表A中第31到第40记录:

1、假设ID是连续的:

    select top 10 * from A where ID not in (select top 30 ID from A)

  或

    select  *  from A where ID between 31 and 40

2、假设ID是不连续的:

     select top 40 * from A except select top 30 * from A

  或

    select top 10 * from A where ID > (select max(ID) from A where ID in (select top 30 ID from A))

     或

    select top 10 * from A where ID not in (select top 30 ID from A) 

2.

原表:
courseid coursename score
-------------------------------------
1 java 70
2 oracle 90
3 xml 40
4 jsp 30
5 servlet 80
-------------------------------------
为了便于阅读,查询此表后的结果显式如下(及格分数为60):
courseid coursename score mark
---------------------------------------------------
1 java 70 pass
2 oracle 90 pass
3 xml 40 fail
4 jsp 30 fail
5 servlet 80 pass
---------------------------------------------------
写出此查询语句
---------------------

select courseid, coursename ,score ,decode(sign(score-60),-1,'fail','pass') as mark from course

sql题练习链接:https://blog.csdn.net/qq_30946681/article/details/80233652

原文地址:https://www.cnblogs.com/gdvxfgv/p/10415039.html