热门关键字: 归纳概括 文章 文章写作 贯彻执行题 提出对策 综合分析
归纳概括题 辅警 辅警 辅警 
  2020最新Java面试题,常见面试题及答案汇总,主要是有答案!
发表评论 来源:网络整理 编辑:admin2 日期:2024-04-03

我发现网上很多Java面试题都没有答案,所以我花了很长时间收集整理了这套Java面试题。 希望对大家有帮助~

以下面试题已整理成Java面试手册,为PDF版本。

私信【资讯】免费领取

1.JDK和JRE有什么区别?

具体来说,JDK实际上包括JRE、编译java源代码的编译器javac以及很多用于调试和分析java程序的工具。 简单来说:如果需要运行java程序,只需要安装JRE即可。 如果需要编写java程序,则需要安装JDK。

2.==和等于有什么区别?

==解读

==对于基本类型和引用类型的作用是不同的,如下:

代码示例:

String x = "string";String y = "string";String z = new String("string");System.out.println(x==y); // trueSystem.out.println(x==z) ; // falseSystem.out.println(x.equals(y)); // trueSystem.out.println(x.equals(z)); // 真的

代码解读:因为x和y指向同一个引用,所以==也为true,并且重写了new String()方法来开辟内存空间,所以==的结果为false,而equals总是比较值,所以结果都是真的。

等于解释

equals本质上就是==,只不过String和Integer重写了equals方法,将其变成了值比较。 只要看下面的代码就可以理解。

首先,让我们看看默认情况下使用 equals 来比较具有相同值的对象。 代码如下:

类 Cat { public Cat(String name) { this.name = name; } 私有字符串名称; 公共字符串 getName() { 返回名称; } public void setName(String name) { this.name = name; Cat c1 = new Cat("王磊");Cat c2 = new Cat("王磊");System.out.println(c1.equals(c2)); // 错误的

输出结果出乎我们的意料,是假的? 到底是怎么回事? 看完equals源码你就知道了。 源码如下:

public boolean equals(Object obj) { return (this == obj);}

事实证明,equals本质上就是==。

那么问题来了,为什么两个值相同的String对象会返回true呢? 代码如下所示:

String s1 = new String("老王");String s2 = new String("老王");System.out.println(s1.equals(s2)); // 真的

同样,当我们进入String的equals方法时,我们就找到了答案。 代码如下:

public boolean equals(Object anObject) { if (this == anObject) { return true; } } } if (anObject instanceof String) { String anotherString = (String)anObject; int n = 值.长度; if (n == anotherString.value .length) { char v1[] = value; char v2[] = anotherString.value; 整数 i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false ; 我++; 返回真; 返回错误;}

原来String重写了Object的equals方法,将引用比较改为值比较。

总结:==对于基本类型来说是值比较,对于引用类型来说是引用比较; 而equals默认是引用比较,但是很多类都重新发明了equals方法,比如String、Integer等,将其变成了Value比较,所以一般情况下equals比较的是值是否相等。

3. 如果两个对象的hashCode()相同,equals()也一定为true,对吧?

不,两个对象的hashCode()是相同的,equals()可能不为true。

代码示例:

String str1 = "呼叫"; String str2 = "呼叫"; System.out.println(String.format("str1:%d | str2:%d", str1.hashCode(),str2.hashCode())); System.out.println(str1.equals(str2));

执行结果:

字符串1:1179395 | 字符串2:1179395

错误的

代码解读:显然“调用”和“厉害的地方”的hashCode()是相同的,但是equals()为假,因为在哈希表中,hashCode()是相等的,也就是说,两个键值对相等,但是 hash 的期望值相等,并不一定意味着键值对相等。

4、java中final的作用是什么? 5. java中Math.round(-1.5)等于什么?

等于-1,因为在数轴上取值时,中间的值(0.5)向右舍入更多事业单位考试题库就点击这里,所以正0.5向上舍入,负0.5直接舍去。

6. String是基本数据类型吗?

String不属于基本类型。 基本类型有8种:byte、boolean、char、short、int、float、long、double,其中String属于对象。

7. Java中有哪些操作字符串的类? 他们之间有什么区别?

对字符串进行操作的类包括:String、StringBuffer 和 StringBuilder。

String、StringBuffer 和 StringBuilder 之间的区别在于 String 声明了一个不可变对象。 每次操作都会生成一个新的String对象,然后将指针指向新的String对象,而StringBuffer和StringBuilder则可以在原对象的基础上进行操作。 所以当字符串的内容经常改变的时候最好不要使用String。

StringBuffer和StringBuilder最大的区别在于,StringBuffer是线程安全的,而StringBuilder是非线程安全的,但是StringBuilder的性能比StringBuffer要高,所以建议在单线程环境下使用StringBuilder,在单线程环境下使用StringBuffer多线程环境。

8. String str="i" 和 String str=new String("i") 一样吗?

不同是因为内存分配方式不同。 String str="i",Java虚拟机会将其分配到常量池中; 而 String str=new String("i") 将分配到堆内存。

9. 如何反转字符串?

使用StringBuilder或stringBuffer的reverse()方法。

示例代码:

// StringBuffer reverseStringBuffer stringBuffer = new StringBuffer();stringBuffer.append("abcdefg");System.out.println(stringBuffer.reverse()); // gfedcba// StringBuilder reverseStringBuilder stringBuilder = new StringBuilder();stringBuilder.append("abcdefg");System.out.println(stringBuilder.reverse()); // gfedcba

10. String类的常用方法有哪些? 11. 抽象类必须有抽象方法吗?

不,抽象类不一定必须有抽象方法。

示例代码:

抽象类 Cat { public static void sayHi() { System.out.println("hi~"); }}

上面的代码中,抽象类没有抽象方法但是可以正常运行。

12.普通类和抽象类有什么区别? 13、抽象类可以用final修饰吗?

不,定义一个抽象类允许其他类继承它。 如果定义为final,则该类不能被继承,会互相冲突。 因此final不能修改抽象类。 如下图,编辑器也会提示错误信息:

14.接口和抽象类有什么区别? 15、Java中有多少种IO流?

按功能分:输入流(input)、输出流(output)。

按类型分:字节流和字符流。

字节流和字符流的区别在于:字节流按照8位以字节为单位传输输入和输出数据,而字符流按照16位以字符为单位传输输入和输出数据。

16、BIO、NIO、AIO有什么区别? 17、Files常用的方法有哪些? 2. 容器 18. 什么是java容器?

常用容器目录:

19. 收藏和收藏有什么区别? 20.List、Set、Map有什么区别? 21.HashMap和Hashtable有什么区别? 22、如何决定使用HashMap还是TreeMap?

对于Map中元素的插入、删除、定位等操作,HashMap是最佳选择。 但是,如果您需要迭代键的有序集合,TreeMap 是更好的选择。 根据集合的大小,将元素添加到 HashMap 并用 TreeMap 替换映射以进行有序键遍历可能会更快。

23、介绍一下HashMap的实现原理?

HashMap概述:HashMap是基于哈希表的Map接口的异步实现。 该实现提供了所有可选的映射操作并允许空值和空键。 此类不保证映射的顺序,特别是它不保证顺序是不可变的。

HashMap数据结构:在Java编程语言中,有两种最基本的结构,一种是数组,另一种是模拟指针(引用)。 所有的数据结构都可以利用这两个基本结构来构造,HashMap也不例外。 HashMap实际上是一种“链表哈希”数据结构,它是数组和链表的组合。

当我们往Hashmap中放入一个元素时,首先根据key的hashcode重新计算hash值,并根据hash值得到该元素在数组中的位置(下标)。 如果数组在该位置已经存储了其他元素,那么在该位置的元素会以链表的形式存储,新添加的放在链头,最先添加的元素放在链表的后面。链的末端。 如果数组中该位置没有元素,则直接将该元素放到数组中该位置。

需要注意的是,HashMap的实现在Jdk 1.8中已经进行了优化。 当链表中的节点数据超过8个时,链表将转为红黑树以提高查询效率,从原来的O(n)变为O(logn)

24、介绍一下HashSet的实现原理? 25.ArrayList和LinkedList有什么区别?

最明显的区别是,ArrayList的底层数据结构是数组,支持随机访问,而LinkedList的底层数据结构是双向循环链表,不支持随机访问。 使用下标访问元素,ArrayList的时间复杂度为O(1),而LinkedList的时间复杂度为O(n)。

26.数组和List之间如何转换? 27.ArrayList和Vector有什么区别? 28.Array和ArrayList有什么区别? 29. Queue中的poll()和remove()有什么区别?

poll()和remove()都是从队列中取出一个元素,但是poll()在获取元素失败时会返回null,但是remove()在失败时会抛出异常。

30. 哪些集合类是线程安全的? 31.什么是迭代器?

迭代器是一种设计模式,它是一个对象,它可以迭代并选择序列中的对象,而开发人员不需要知道序列的底层结构。 迭代器通常被称为“轻量级”对象,因为它们的创建成本很低。

32.如何使用迭代器? 有什么特点?

Java中的Iterator函数比较简单,只能朝一个方向移动:

(1) 使用iterator()方法要求容器返回一个Iterator。 第一次调用 Iterator 的 next() 方法时,它返回序列的第一个元素。 注意:iterator()方法是java.lang.Iterable接口,被Collection继承。

(2) 使用next()获取序列中的下一个元素。

(3) 使用hasNext()检查序列中是否还有元素。

(4) 使用remove()删除迭代器新返回的元素。

Iterator是Java迭代器最简单的实现。 为List设计的ListIterator具有更多的功能。 它可以从两个方向遍历List,也可以向List插入和删除元素。

33.Iterator和ListIterator有什么区别? 3. 多线程 35. 并行性和并发性有什么区别?

因此,并发编程的目标是充分利用处理器的每个核心,以达到最高的处理性能。

36.线程和进程有什么区别?

简而言之,进程是程序运行和资源分配的基本单位。 一个程序至少有一个进程,一个进程至少有一个线程。 进程在执行时拥有独立的内存单元,多个线程共享内存资源,减少了切换次数,效率更高。 线程是进程的实体,是CPU调度和分派的基本单位,是比程序更小的、可以独立运行的基本单位。 同一进程中的多个线程可以并发执行。

37.什么是守护线程?

守护线程是一个服务线程。 准确的说,它是为其他线程服务的。

38.创建线程有哪些方式?

①. 继承Thread类创建线程类

②. 通过Runnable接口创建线程类

③. 通过Callable和Future创建线程

39. 可运行和可调用之间有什么区别?

这是一个有点深奥的问题,同时也显示了一个Java程序员可以获得的知识的广度。

40.线程有哪些状态?

线程通常有五种状态:创建、就绪、运行、阻塞和死亡。

41. sleep()和wait()有什么区别?

sleep():该方法是线程类(Thread)的静态方法,它允许调用线程进入睡眠状态,并给其他线程执行机会。 睡眠时间结束后,线程进入就绪状态,与其他线程竞争CPU的执行时间。 因为 sleep() 是静态方法,所以它不能更改对象的机器锁。 当在synchronized块中调用sleep()方法时,虽然线程进入睡眠状态,但该对象的机器锁并没有释放,其他线程仍然无法访问该对象。

wait():wait()是Object类的一个方法。 当线程执行wait方法时,它会进入与该对象相关的等待池,并释放该对象的机器锁,以便其他线程可以访问它。 可以通过notify、notifyAll方法来唤醒等待的线程。

42.notify()和notifyAll()有什么区别? 43.线程的run()和start()有什么区别?

每个线程通过特定Thread对象对应的run()方法来完成自己的操作。 run() 方法称为线程体。 通过调用Thread类的start()方法来启动一个线程。

start()方法用于启动一个线程,真正实现多线程操作。 此时不需要等待run方法体代码执行完毕,可以直接继续执行下面的代码; 此时线程处于就绪状态,没有运行。 然后通过这个Thread类调用方法run()来完成其运行状态。 这里的run()方法称为线程体,里面包含了线程要执行的内容。 Run 方法结束,线程终止。 然后CPU 调度其他线程。

run()方法就在这个线程中。 它只是线程中的函数,并不是多线程的。 如果直接调用run(),其实就相当于调用一个普通的函数。 如果直接使用run()方法,则必须等待run()方法执行完成后才能执行下面的代码。 因此,仍然只有一条执行路径,根本没有线程。 特点,所以多线程执行时应该使用start()方法而不是run()方法。

44、创建线程池有哪些方式?

①. newFixedThreadPool(int nThreads)

创建固定长度的线程池。 每次提交任务时都会创建一个线程,直到达到线程池的最大数量。 此时,螺纹尺寸将不再改变。 当线程因意外错误而结束时,线程池将得到补充。 一个新线程。

②. newCachedThreadPool()

创建可缓存的线程池。 如果线程池的大小超过处理需求,空闲线程将被自动回收。 当需求增加时,可以自动添加新线程。 线程池的大小没有限制。

③. newSingleThreadExecutor()

这是一个单线程执行器,它创建单个工作线程来执行任务。 如果该线程异常结束,则会创建一个新的线程来替代它; 其特点是可以保证按照队列中任务的顺序串行执行。

④. newScheduledThreadPool(int corePoolSize)

创建固定长度的线程池,以延迟或定时的方式执行任务,类似于Timer。

45、线程池有哪些状态?

线程池有5种状态:Running、ShutDown、Stop、Tidying、Termied。

线程池状态切换框架图:

46.线程池中的submit()和execute()方法有什么区别?

47、Java程序中如何保证多线程的安全运行?

线程安全体现在三个方面:

48、多线程锁升级的原理是什么?

在Java中,有四种锁状态。 级别从低到高依次为:无状态锁、偏向锁、轻量级锁、重量级状态锁。 这些州将随着竞争逐渐升级。 锁可以升级但不能降级。

锁升级流程图示:

49.什么是死锁?

死锁是指两个或多个进程在执行过程中争夺资源或相互通信而导致的阻塞现象。 没有外力,他们就无法前进。 此时就称系统处于死锁状态或者系统出现死锁。 这些总是互相等待的进程称为死锁进程。 它是操作系统级别的错误,是进程死锁的缩写。 它是由 Dijkstra 在 1965 年研究银行家算法时首次提出的。 它是计算机操作系统乃至整个并发编程领域最难处理的问题之一。

50.如何防止死锁?

产生死锁的四个必要条件:

这四个条件是死锁产生的必要条件。 只要系统中发生死锁,这些条件就一定成立。 只要不满足上述条件之一,就不会发生死锁。

通过了解死锁产生的原因,特别是死锁产生的四个必要条件,就可以最大程度地避免、预防和消除死锁。

因此,在系统设计、进程调度等方面,要注意如何防止这四个必要条件不成立,以及如何确定合理的资源分配算法,避免进程永久占用系统资源。

另外,还需要防止进程在等待状态时占用资源。 因此,必须合理规划资源配置。

51.什么是ThreadLocal? 使用场景有哪些?

线程局部变量是仅限于线程的变量。 它们属于线程本身,不在多个线程之间共享。 Java提供了ThreadLocal类来支持线程局部变量,这是实现线程安全的一种方式。 但在托管环境(例如 Web 服务器)中使用线程局部变量时要特别小心,其中工作线程的生命周期比任何应用程序变量的生命周期都长。 一旦任何线程局部变量在工作完成后没有释放,Java应用程序就会面临内存泄漏的风险。

52、介绍一下synchronized的底层实现原理?

Synchronized可以保证当一个方法或代码块运行时,只有一个方法可以同时进入临界区。 它还可以保证共享变量的内存可见性。

Java中的每个对象都可以作为一个锁,这是synchronized实现同步的基础:

53.synchronized 和 volatile 有什么区别? 54.synchronized和Lock有什么区别? 55.synchronized和ReentrantLock有什么区别?

synchronized 与 if、else、for、while 是同一个关键字,并且 ReentrantLock 是一个类。 这是两者的本质区别。 由于ReentrantLock是一个类,因此它提供了比synchronized更多、更灵活的功能。 它可以被继承,可以有方法,并且可以有各种类变量。 ReentrantLock相比synchronized的可扩展性体现在几点:

另外,两者的加锁机制其实也不一样:ReentrantLock调用Unsafe的park方法在底层加锁,而synchronized则要对对象头中的mark字进行操作。

56.请介绍一下原子的原理?

Atomic包中的类的基本特点是,在多线程环境下,当多个线程同时操作单个变量(包括基本类型和引用类型)时,它们是互斥的,即当多个线程同时对变量的值进行操作更新时,只有一个线程可以成功,不成功的线程可以像自旋锁一样继续尝试,直到执行成功。

Atomic系列类中的核心方法会调用unsafe类中的几个本地方法。 我们首先需要知道的一件事是Unsafe类,它的全名是:sun.misc.Unsafe。 此类包含大量对 C 代码的操作,包括许多直接内存分配和对原子操作的调用。 之所以被标记为非Safe,是告诉大家,这里面大量的方法调用会存在安全风险,需要谨慎使用,否则会导致严重的后果。 例如,通过unsafe分配内存时,如果指定某些区域,可能会导致一些类似于C++的问题。 指针越过边界到达其他进程。

4. 反射 57. 什么是反射?

反射主要是指程序访问、检测和修改自身状态或行为的能力。

Java反射:

在Java运行环境中,对于任何一个类,你能知道这个类有哪些属性和方法吗?对于任何一个对象,它的任何一个方法都可以被调用吗?

Java反射机制主要提供以下功能:

58.什么是java序列化? 什么时候需要序列化?

简单来说,就是保存内存中各种对象的状态(就是实例变量,而不是方法),并将保存的对象状态读出。 虽然你可以使用自己的各种方法来保存对象状态,但是Java为你提供了一种应该比你自己的更好的保存对象状态的机制,那就是序列化。

什么时候需要序列化:

a) 当要将内存中的对象状态保存到文件或数据库时;

b) 当你想使用套接字通过网络传输对象时;

c) 当你想通过RMI传输对象时;

59.什么是动态代理? 有哪些应用?

动态代理:

当您想要向实现接口的类中的方法添加一些额外的处理时。 比如添加日志、添加事务等。你可以为这个类创建一个代理,所以名字暗示你创建一个新的类。 该类不仅包含原有类方法的功能,而且在原有的基础上增加了一个经过额外处理的新类。 这个代理类不是定义的,而是动态生成的。 具有解耦意义、灵活性、可扩展性强。

动态代理的应用:

60.如何实现动态代理?

首先,必须定义一个接口,并且必须有一个 InitationHandler(将实现该接口的类的对象传递给它)来处理该类。 还有一个工具类Proxy(习惯上称其为代理类,因为调用其newInstance()可以生成代理对象,其实它只是一个生成代理对象的工具类)。 使用IncationHandler拼接代理类的源码,编译生成代理类的二进制代码,使用加载器加载,实例化生成代理对象,最后返回。

5. 对象复制 61. 为什么使用克隆

如果要处理一个对象并保留原始数据以供后续操作,则需要克隆它。 Java 语言中的克隆目标是类的实例。

62. 如何实现对象克隆?

有两种方法:

1)。 实现Cloneable接口并重写Object类中的clone()方法;

2)。 实现Serialized接口,通过对象序列化和反序列化来实现克隆,可以实现真正的深度克隆。 代码如下:

导入java.io.ByteArrayInputStream;导入java.io.ByteArrayOutputStream;导入java.io.ObjectInputStream;导入java.io.ObjectOutputStream;导入java.io.Serializable; 公共类 MyUtil { 私有 MyUtil() { 抛出新的 AssertionError(); } @SuppressWarnings("unchecked") public static T clone(T obj) throws Exception { ByteArrayOutputStream bout = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bout); oos.writeObject(obj); ByteArrayInputStream bin = new ByteArrayInputStream(bout .toByteArray()); ObjectInputStream ois = new ObjectInputStream(bin); return (T) ois.readObject(); // 注意:调用 ByteArrayInputStream 或 ByteArrayOutputStream 对象的 close 方法是没有意义的 // 这两个基于内存的流只需要垃圾收集器就可以通过清理对象来释放资源,这与释放外部资源(如作为文件流)}}

这是测试代码:

导入java。 io。 可串行化; /** * Human * @author nnngu * */class Person 实现 Serialized { private static Final long serialVersionUID = -96042305L; 私有字符串名称; // 名称 private int Age; // 私家车车龄; // 汽车 public Person(String name, int Age, Car car) { this. 姓名=姓名; 这。 年龄=年龄; 这。 汽车=汽车; } public String getName() { 返回名称; } public void setName(字符串名称) { this. 姓名=姓名; } public int getAge() { 返回年龄; } 公共无效 setAge(int 年龄) { this.

年龄=年龄; } 公共汽车 getCar() { 返回汽车; } public void setCar(Car car) { this. 汽车=汽车; } @Override public String toString() { return "Person [name=" + name + ",age=" +age + ", car=" + car + "]"; } } /** * 小汽车类* @author nnngu * */class Car 实现 Serialized { private static Final long serialVersionUID = -57603702L; 私人琴弦品牌; // 品牌私有 int maxSpeed; // 最高时速 public Car(String Brand, int maxSpeed) { this. 品牌=品牌; 这。

最大速度=最大速度; } public String getBrand() { 返回品牌; } public void setBrand(String Brand) { this. 品牌=品牌; } public int getMaxSpeed() { 返回 maxSpeed; } 公共无效 setMaxSpeed(int maxSpeed) { this. 最大速度=最大速度; } @Override public String toString() { return "汽车 [brand=" + 品牌 + ", maxSpeed=" + maxSpeed + "]"; } }class CloneTest { public static void main(String[] args) { try { Person p1 = new Person("郭靖", 33, new Car("奔驰", 300)); 人 p2 = MyUtil.

克隆(p1); // 深度克隆 p2. 获取汽车()。 setBrand("比亚迪"); // 修改与克隆的 Person 对象 p2 关联的汽车对象的品牌属性 // 与原始 Person 对象 p1 关联的汽车不会受到任何影响 // 因为与 Person 对象关联的汽车对象是克隆的 System was也克隆了。 出去。 打印(p1); } catch (异常 e) { e. printStackTrace(); } }}

注意:基于序列化和反序列化的克隆不仅仅是深度克隆,更重要的是,通过泛型限定,可以检查要克隆的对象是否支持序列化。 这个检查是由编译器完成的,而不是在运行时抛出异常。 这种方案显然比使用Object类的clone方法来克隆对象要好。 在编译时暴露问题总是比在运行时暴露问题要好。

63.深拷贝和浅拷贝有什么区别? 6.Java Web64。 jsp和servlet有什么区别?

jsp编译后就成为Servlet。 (JSP的本质是Servlet,JVM只能识别java类,不能识别JSP代码。Web容器将JSP代码编译成JVM可以识别的java类)

JSP更擅长页面显示,servlet更擅长逻辑控制。

Servlet 中没有内置对象。 Jsp中的内置对象必须通过HttpServletRequest对象、HttpServletResponse对象和HttpServlet对象来获取。

Jsp是Servlet的简化。 使用Jsp只需要完成程序员需要输出到客户端的内容即可。 如何将Jsp中的Java脚本嵌入到类中是由Jsp容器完成的。 Servlet是一个完整的Java类,该类的Service方法用于生成对客户端的响应。

65、jsp中有哪些内置对象? 有哪些功能?

JSP有9个内置对象:

66.说说jsp的四个作用域?

JSP中的四个作用域包括页面、请求、会话和应用程序。 具体来说:

67.session和cookie有什么区别? 68. 介绍一下session的工作原理?

其实session就是一个存在于服务器上的类似于哈希表的文件。 我们需要的信息都存储在里面,当我们需要使用的时候就可以取出来。 它类似于一张大地图。 里面的key存储的是用户的sessionid。 用户向服务器发送请求时会带上这个sessionid。 这时候就可以从中提取出对应的值了。

69. 如果客户端禁用cookie,会话还可以使用吗?

Cookie和Session一般被认为是两个独立的东西。 Session采用的是在服务器端维护状态的方案,而Cookie则采用的是在客户端维护状态的方案。 但是为什么禁用cookie就无法获取Session呢? 因为Session是通过Session ID来确定当前会话对应的服务器Session的,而Session ID是通过Cookie来传递的,禁用Cookie就相当于丢失了Session ID,从而导致Session丢失。

假设用户在关闭Cookie时使用Session,则实现方法如下:

在php.ini配置文件中设置“session.use_trans_sid = 1”,或者在编译时打开“--enable-trans-sid”选项,让PHP自动跨页面传递Session ID。

通过 URL 手动传递值并通过隐藏表单传递会话 ID。

将Session ID保存在文件、数据库等中,在跨页面过程中手动调用。

如何获取信息! 转发文章+私信【资讯】

公务员考试网推荐专题
你可能还会关注的文章
公务员考试网最新文章
公务员考试网热门文章
公务员考试网推荐
 
网站留言 | 关于我们 | 广告业务 | 信息反馈 | 合作伙伴 | 网站地图
版权所有 2007-2023 甘肃公务员考试网(www.gsgwyw.com)
Copyright © 2007-2023 www.gsgwyw.com Incorporated. All rights reserved.