java笔试题总结
1.标志符的命名基本规则如下:
所有的标志符都必须以一个字母、下划线或美元符号“$”开头,后面的字符可以包含字母、数字、下划线和美元符号。
2.构造函数
作用:一般用来初始化成员属性和成员方法的,即new对象产生后,就调用了对象了属性和方法。
特点:
1)、函数名与类名相同
2)、不用定义返回值类型。(不同于void类型返回值,void是没有具体返回值类型;构造函数是连类型都没有)
3)、不可以写return语句。(返回值类型都没有,也就不需要return语句了)
注:一般函数不能调用构造函数,只有构造函数才能调用构造函数。
3.Java编译单元为什么只能有一个public类,而且源文件名必须要与类名相同
Java编程思想中的一段话:
当编写一个java源代码文件时,此文件通常被称为编译单元(有时也被称为转译单元)。每个编译单元都必须有一个后缀名.java,而在编译单元内则可以有一个public类,该类的名称必须与文件的名称相同(包括大小写,但不包括文件的后缀名.java)。每个编译单元只能有一个public类,否则编译器就不会接受。如果在该编译单元之中还有额外的类的话,那么在包之外的世界是无法看见这些类的,这是因为它们不是public类,而且它们主要用来为主public类提供支持。
https://blog.csdn.net/WaitForFree/article/details/51033457
4.多种修饰符的连用问题: public protected default private static final abstract
可以连用: public static private static public final public static final
不可以连用:abstract final void eat(); private abstract void eat(); static abstract void eat(); abstract不能和final,private,static连用
5.Java中的abstract方法和abstract类的问题
抽象类和抽象方法的关系:含有抽象方法的类一定是抽象类,抽象类里不一定含有抽象方法。
抽象类存在的意义是用来被继承的。一个类继承了一个抽象类,必须实现抽象类里面所有的抽象方法,否则,此类也是抽象类。
abstract修饰符用来修饰类和成员方法
1:用abstract修饰的类表示抽象类,抽象类位于继承树的抽象层,抽象类不能被实例化。
2:用abstract修饰的方法表示抽象方法,抽象方法没有方法体。抽象方法用来描述系统具有什么功能,但不提供具体的实现。
abstract 规则:
1:抽象类可以没有抽象方法,但是有抽象方法的类必须定义为抽象类,如果一个子类继承一个抽象类,子类没有实现父类的所有抽象方法,那么子类也要定义为抽象类,否则的话编译会出错的。
2:抽象类没有构造方法,也没有抽象静态方法。但是可以有非抽象的构造方法
3:抽象类不能被实例化,但是可以创建一个引用变量,类型是一个抽象类,并让它引用非抽象类的子类的一个实例
4:不能用final 修饰符修饰
6.this关键字的作用
1.调用本类属性 this.+属性,当前对象中的属性
2.调用本类方法(基本、构造)
普通方法:this.方法名称(参数...)
构造方法:this(参数...)
注意:
1、由于构造方法是在实例化对象时被自动调用的,也就是说在类中的所有方法中,只有构造方法是被优先调用的,
所以使用this调用构造方法必须也只能放在构造方法的首行
2、this调用构造方法时一定要留下一个构造方法作为出口,即程序中至少存在一个构>造方法是不使用this调用其他构造方法的
3.表示当前对象(相对概念)
7.super关键字的作用
1.super可用于访问父类被子类隐藏或着覆盖的方法和属性,使用形式为super.方法(属性)
2.在类的继承中,子类的构造方法中默认会有super()语句存在(默认隐藏),相当于执行父类的相应构造方法中的语句,若显式使用则必须位于类的第一行
3.对于父类有参的构造方法,super不能省略,否则无法访问父类的有参构造方法,使用形式为super(xx,xx...)
8.注释
一、单行注释(也可以多行注释)
1、样式:// 我是被注释的内容
2、快捷键:ctrl+/ 或 ctrl+shift+C
二、多行注释(也可以单行注释)
1、样式:/* 我是被注释的内容 */
2、快捷键:ctrl+shift+/
三、文档注释
1、样式:/** 我是被注释的文档 */
2、快捷键:Alt+shift+J
3、修改文档注释的文档内容:
打开eclipse
Window-->Preferences-->Java-->Code Style --> Code Templates --> Comments --> types --> Edit
9.注解
注解根据来源可分为: 系统注解(自带的,取决于JDK版本)、自定义注解及第三方注解
系统注解根据用途又可分为: java内置注解和元注解
根据运行机制(保留到什么时候)可分为: 源码注解、编译注解和运行注解
1.java内置注解
例如@Override
覆盖父类方法
2.元注解
用来注解其他注解
3.第三方注解
例如@Controller
声明为控制器,可返回jsp、html页面的名称并跳转到相应页面
备注:springMVC中,控制器就是一个其方法中添加了@RequestMapping来处理请求的类
SpringMVC,MyBatis等等中的注解都是第三方注解
10.类和对象的关系
类:事物的描述。是具备某些共同特征的实体的集合,它是一种抽象的数据类型,它是对所具有相同特征实体的抽象。在面向对象的程序设计语言中,类是对一类“事物”的属性与行为的抽象。
对象:该类事物的实例。在Java中通过new进行创建。是一个真实世界中的实体,对象与实体是一一对应关系的,意思就是现实世界的每一个实体都是一个对象,所以对象是一个具体的概念。对象是一种个性的表示,表示一个独立的个体,每个对象拥有自己独立的属性,依靠属性来区分不同对象。
类和对象的区别
1,类是一个抽象的概念,它不存在于现实中的时间/空间里,类只是为所有的对象定义了抽象的属性与行为。就好像“Person(人)”这个类,它虽然可以包含很多个体,但它本身不存在于现实世界上。
2,对象是类的一个具体。它是一个实实在在存在的东西。
3,类是一个静态的概念,类本身不携带任何数据。当没有为类创建任何对象时,类本身不存在于内存空间中。
4,对象是一个动态的概念。每一个对象都存在着有别于其它对象的属于自己的独特的属性和行为。对象的属性可以随着它自己的行为而发生改变。
类是对象的模板,对象是类的实例。类只有通过对象才可以使用,而在开发之中应该先产生类,之后再产生对象。类不能直接使用,对象是可以直接使用的。
11.Java编译器自动导入而无需在程序中用import导入的包
Java语言中的java.lang包是由编译器直接自动导入的,因此,编程时使用该包中的类,可省去 import导入。使用其他包中的类,必须用import导入
12.访问权限
访问权限控制: 指的是本类及本类内部的成员(成员变量、成员方法、内部类)对其他类的可见性,即这些内容是否允许其他类访问。
访问权限 | 本类 | 本包的类 | 子类 | 非子类的外包类 |
---|---|---|---|---|
public | 是 | 是 | 是 | 是 |
protected | 是 | 是 | 是 | 否 |
default | 是 | 是 | 否 | 否 |
private | 是 | 否 | 否 | 否 |
1、public: 所修饰的类、变量、方法,在内外包均具有访问权限;
2、protected: 这种权限是为继承而设计的,protected所修饰的成员,对所有子类是可访问的,但只对同包的类是可访问的,对外包的非子类是不可以访问;
3、包访问权限(default): 只对同包的类具有访问的权限,外包的所有类都不能访问;
4、private: 私有的权限,只对本类的方法可以使用;
13.线程
-
线程状态。
线程可以处于以下状态之一:
* NEW
还未调用 start() 方法
尚未启动的线程处于此状态。
* RUNNABLE
调用了 start() ,此时线程已经准备好被执行,处于就绪队列
在Java虚拟机中执行的线程处于此状态。
* BLOCKED
线程阻塞于锁或者调用了 sleep
被阻塞等待监视器锁定的线程处于此状态。
* WAITING
正在等待另一个线程执行特定动作的线程处于此状态。
* TIMED_WAITING
与 WAITING 的区别是可以在特定时间后自动返回
正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
* TERMINATED
执行完毕或者被其他线程杀死
已退出的线程处于此状态。
一个线程可以在给定时间点处于一个状态。 这些状态是不反映任何操作系统线程状态的虚拟机状态。
-
线程创建方式(3种)
线程的创建有三种方式:继承Thread,实现Runnable接口,利用Callable跟Future
- 一、
继承Thread
- 1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。
- 2)创建Thread子类的实例,即创建了线程对象。
- 3)调用线程对象的start()方法来启动该线程。
public class FirstMethod extends Thread {
@Override
public void run() {
super.run();
}
}
FirstMethod firstMethod = new FirstMethod();
firstMethod.start();
- 二、
实现Runnable接口
- 1)定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
- 2)创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
- 3)调用线程对象的start()方法来启动该线程。
public class SecondMethod implements Runnable{
@Override
public void run() {
}
}
SecondMethod secondMethod=new SecondMethod();
new Thread(secondMethod).start();
- 三、
通过Callable跟FutureTask创建线程
- 1)创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
- 2)创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
- 3)使用FutureTask对象作为Thread对象的target创建并启动新线程。
- 4)调用FutureTask对象的get()方法来获得子线程执行结束后的返回值
public class ThirdMethod implements Callable<String> {
@Override
public String call() throws Exception {
return Thread.currentThread().getName();
}
}
ThirdMethod thirdMethod=new ThirdMethod();
FutureTask<String> futureTask=new FutureTask<String>(thirdMethod);
try {
String threadName = futureTask.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
-
四、
通过线程池创建线程
Executor框架包括:线程池,Executor,Executors,ExecutorService,CompletionService,Future,Callable等。
略 -
四种创建线程方法对比
实现Runnable和实现Callable接口的方式基本相同,不过是后者执行call()方法有返回值,后者线程执行体run()方法无返回值,因此可以把这两种方式归为一种这种方式与继承Thread类的方法之间的差别如下:
1、线程只是实现Runnable或实现Callable接口,还可以继承其他类。
2、这种方式下,多个线程可以共享一个target对象,非常适合多线程处理同一份资源的情形。
3、但是编程稍微复杂,如果需要访问当前线程,必须调用Thread.currentThread()方法。
4、继承Thread类的线程类不能再继承其他父类(Java单继承决定)。
5、前三种的线程如果创建关闭频繁会消耗系统资源影响性能,而使用线程池可以不用线程的时候放回线程池,用的时候再从线程池取,项目开发中主要使用线程池
注:在前三种中一般推荐采用实现接口的方式来创建多线程-
线程常用方法
-
方法 | 作用 |
---|---|
public void start() | 使该线程开始执行;Java 虚拟机调用该线程的 run 方法。 |
public void run() | 如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。 |
public final void setName(String name) | 改变线程名称,使之与参数 name 相同 |
public final void setPriority(int piority) | 更改线程的优先级。 |
public final void setDaemon(boolean on) | 将该线程标记为守护线程或用户线程。 |
public final void join(long millisec) | 等待该线程终止的时间最长为 millis 毫秒。 |
public void interrupt() | 中断线程。 |
public final boolean isAlive() | 测试线程是否处于活动状态。 |
public static void static yield() | 暂停当前正在执行的线程对象,并执行其他线程。 |
public static void sleep(long millisec) | 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。 |
public static Thread currentThread() | 返回对当前正在执行的线程对象的引用。 |
-
停止线程
在Java中有以下3种方法可以终止正在运行的线程:
1.使用退出标志,使线程正常退出,也就是当run方法完成后线程终止
2.使用stop方法强行终止线程,但是不推荐使用这个方法,因为stop和suspend及resume一样,都是作废过期的方法,使用他们可能产生不可预料的结果。
3.使用interrupt方法中断线程,但这个不会终止一个正在运行的线程,还需要加入一个判断才可以完成线程的停止。
14.线程和进程有什么区别?
答:一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。别把它和栈内存搞混,每个线程都拥有单独的栈内存用来存储本地数据。
15.启动一个线程是调用run()还是start()方法?
答:启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM 调度并执行,这并不意味着线程就会立即运行。run()方法是线程启动后要进行回调(callback)的方法。
16.Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,它们有什么区别?
答:sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程暂停执行指定的时间,将执行机会(CPU)让给其他线程,但是对象的锁依然保持,因此休眠时间结束后会自动恢复(线程回到就绪状态)。wait()是Object类的方法,调用对象的wait()方法导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),只有调用对象的notify()方法(或notifyAll()方法)时才能唤醒等待池中的线程进入锁池(lock pool),如果线程重新获得对象的锁就可以进入就绪状态。
https://blog.csdn.net/u014561933/article/details/58639411
17.线程的sleep()方法和yield()方法有什么区别?
答:
① sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;
② 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态;
③ sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常;
④ sleep()方法比yield()方法(跟操作系统CPU调度相关)具有更好的可移植性。
18.n阶蛇形矩阵
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while(input.hasNext()) {
int n = input.nextInt();
printMatrix(n);
}
input.close();
}
public static void printMatrix(int n) {
int[][] arr = new int[n][n];
int x = 0, y = 0;
int num = 1; // num不能为0,否则死循环
int sum = n * n;
arr[0][0] = 1;
while(num < sum) {
// 向右移动,
// 直到到达边界,或者向右移动的下一个元素不为0(新的已经填充的边界)
while(y + 1 < n && arr[x][y + 1] == 0)
arr[x][++y] = ++num;
// 向下移动
while(x + 1 < n && arr[x + 1][y] == 0)
arr[++x][y] = ++num;
// 向左移动
while(y - 1 >= 0 && arr[x][y - 1] == 0)
arr[x][--y] = ++num;
// 向上移动
while(x - 1 >= 0 && arr[x - 1][y] == 0)
arr[--x][y] = ++num;
}
// 打印输出
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
//System.out.println(arr[i][j] + " ");
// 带格式的打印 printf()
System.out.printf("%4d", arr[i][j]);
}
System.out.println();
}
}
}