美文网首页
Java基础知识大全

Java基础知识大全

作者: 海云志 | 来源:发表于2018-09-05 10:09 被阅读11次

一、基础知识: 

原文地址

1、JVM、JRE和JDK的区别: 

JVM(Java Virtual Machine):java虚拟机,用于保证java的跨平台的特性。 

java语言是跨平台,jvm不是跨平台的。 

JRE(Java Runtime Environment):java的运行环境,包括jvm+java的核心类库。 

JDK(Java Development Kit):java的开发工具,包括jre+开发工具 

2、环境变量path和classpath的作用是什么? 

(1)path是配置Windows可执行文件的搜索路径,即扩展名为.exe的程序文件所在的目录, 

用于指定DOS窗口命令的路径。 

(2)Classpath是配置class文件所在的目录,用于指定类搜索路径,JVM就是通过它来寻找该类的class类文件的

3、变量有什么用?为什么要定义变量?什么时候用? 

变量的作用:用来存储数据。 

为什么要定义变量:用来不断的存放同一类型的常量,并可以重复使用

4、&和&&的区别? 

(1)&&会出现短路,如果可以通过第一个表达式判断出整个表达式的结果,则不继续后面表达式的运算; 

只能操作boolean类型数据; 

(2)&不会出现短路,将整个表达式都运算。既可以操作boolean数据还可以操作数。 

5、标示符命名规则: 

由数字(0-9),大小写英文字母,以及_和$组成。 

不能以数字开头。 

不能使用关键字来自定义命名。 

6、数据类型: 

(1)基本数据类型(4类8种): 

整数类型:byte、short、int、long 

浮点数类型:float、double 

字符类型:char 

布尔类型:boolean(ture false) 

(2)引用数据类型: 

类 

接口 

数组 

7、类型转换 

精度从高到低 double float long int short(char) byte 

(1)自动类型转换 将一个低精度—高精度 

(2)强制类型转换 将一个高精度—低精度(精度会下降) 

8、java语言的三种技术架构 

J2EE:企业版 

是为开发企业环境下的应用程序提供的一套解决方案。 

该技术体系中包含的技术如 Servlet、Jsp等,主要针对于Web应用程序开发。 

J2SE:标准版 

是为开发普通桌面和商务应用程序提供的解决方案。 

该技术体系是其他两者的基础,可以完成一些桌面应用程序的开发。 

比如Java版的扫雷。 

J2ME:小型版 

是为开发电子消费产品和嵌入式设备提供的解决方案。 

该技术体系主要应用于小型电子消费类产品,如手机中的应用程序等。 

9、java的跨平台性: 

通过Java语言编写的应用程序在不同的系统平台上都可以运行。 

跨平台的原因: 

只要在需要运行java应用程序的操作系统上,先安装一个Java虚拟机(JVM Java Virtual Machine)即可。 

由JVM来负责Java程序在该系统中的运行。 

10、有符号数据的表示法(次重点) 

原码,反码(原码取反),补码(反码+1)。

11、函数 

定义:函数就是定义在类中的具有特定功能的一段独立小程序。 

特点: 

定义函数可以将功能代码进行封装 

便于对该功能进行复用 

函数只有被调用才会被执行 

函数的出现提高了代码的复用性 

对于函数没有具体返回值的情况,返回值类型用关键字void表示, 

那么该函数中的return语句如果在最后一行可以省略不写。 

函数的应用两个明确: 

明确要定义的功能最后的结果是什么? 

明确在定义该功能的过程中,是否需要未知内容参与运算 

12、重载: 

概念:在同一个类中,允许存在一个以上的同名函数,只要它们的参数个数或者参数类型不同即可。 

特点:与返回值类型无关,只看参数列表(参数类型以及参数个数)。 

好处:方便于阅读,优化了程序设计。 

13、数组: 

概念:同一种数据类型的集合。 

好处:可以自动给数组中的元素从0开始编号,方便操作这些元素。 

14、内存结构: 

栈内存:用于存储局部变量,当数据使用完,所占空间会自动释放。 

堆内存:数组和对象,通过new建立的实例都存放在堆内存中。 

方法区:静态成员、构造函数、常量池、线程池 

本地方法区:window系统占用 

寄存器:

二、面向对象 

1、面向对象思想: 

(1)概述:面向对象是相对于面向过程而言的,面向过程强调的是功能,面向对象强调的是将功能封装进对象, 

强调具备功能的对象; 

(2)思想特点: 

A:是符合人们思考习惯的一种思想; 

B:将复杂的事情简单化了; 

C:将程序员从执行者变成了指挥者;

比如我要达到某种结果,我就寻找能帮我达到该结果的功能的对象,如我要洗衣服我就买洗衣机, 

至于怎么洗我不管。 

(3)特征: 

封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式 

继承: 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义 

这些属性和行为,只要继承那个类即可。 

多态: 一个对象在程序不同运行时刻代表的多种状态,父类或者接口的引用指向子类对象

2、类和对象: 

类:对现实世界中某类事物的描述,是抽象的,概念上的定义。 

对象:事物具体存在的个体。 

3:成员变量和局部变量的区别(重点) 

(1)作用域 

成员变量:针对整个类有效。 

局部变量:只在某个范围内有效。(一般指的就是方法,语句体内) 

(2)存储位置 

成员变量:随着对象的创建而存在,随着对象的消失而消失,存储在堆内存中。 

局部变量:在方法被调用,或者语句被执行的时候存在,存储在栈内存中。 

当方法调用完,或者语句结束后,就自动释放。 

(3)初始值 

成员变量:有默认初始值。 

局部变量:没有默认初始值,使用前必须赋值。 

4、匿名对象 

(1)匿名对象就是没有名字的对象。是对象的一种简写形式。 

(2)应用场景 

A:只调用一次类中的方法。 

B:可以作为实际参数在方法传递中使用 

5、封装: 

指隐藏对象的属性和实现细节,仅对外提供公共访问方式;比如电脑机箱、笔记本等 

好处: 

将变化隔离; 

方便使用; 

提高复用性; 

提高安全性 

6、关键字private:封装在代码中的体现 

(1)私有的意思,权限修饰符 

(2)用来修饰成员变量和成员函数 

(3)用private修饰的成员只在本类中有效 

(4)私有是封装的一种体现 

7、构造方法: 

(1)特点: 

方法名与类名相同 

没有返回类型 

没有返回值 

(2)作用:构造函数是用于创建对象,并对其进行初始化赋值,对象一建立就自动调用相对应的构造函数, 

(3)构造方法的注意事项: 

A:如果一个自定义类没有构造方法,系统会默认给出一个无参构造方法。 

B:如果一个自定义类提供了构造方法,那么,系统将不再给出无参构造方法。 

这个时候,你可以不使用无参构造方法。 

如果你想使用,那么,就必须手动给出无参构造方法。

建议:一般情况下,我们的自定义类都要手动给出无参构造方法。 

(4)构造方法和成员方法的区别 

A:格式区别 

构造方法和类名相同,并且没有返回类型,也没有返回值。 

普通成员方法可以任意起名,必须有返回类型,可以没有返回值。 

B:作用区别 

构造方法用于创建对象,并进行初始化值。 

普通成员方法是用于完成特定功能的。 

C:调用区别 

构造方法是在创建对象时被调用的,一个对象建立,只调用一次相应构造函数 

普通成员方法是由创建好的对象调用,可以调用多次

8、构造代码块: 

(1)作用:给对象进行初始化,对象一建立就执行,而且优先于构造函数执行 

(2)构造代码块和构造函数的区别: 

构造代码块是给所有不同对象的共性进行统一初始化 

构造函数是给对应的对象进行初始化 

9、this关键字 

(1)this关键字代表本类对象的一个引用,谁调用this所在的方法,this就代表谁 

(2)this的使用场景 

A:用于区分同名成员变量和局部变量; 

B:在定义函数时,该函数内部要用到调用该函数的对象时,因为此时对象还没建立,故this代表此对象 

B:构造函数间调用 

**这个时候,this(参数)必须作为第一条语句存在。 

10、Person p = new Person();在内存中做了哪些事情。 

(1)将Person.class文件加载进内存中。 

(2)如果p定义在主方法中,那么,就会在栈空间开辟一个变量空间p。 

(3)在堆内存给对象分配空间。 

(4)对对象中的成员进行默认初始化。 

(5)对对象中的成员进行显示初始化。 

(6)调用构造代码块对对象进行初始化。(如果没有就不执行) 

(7)调用构造方法对对象进行初始化。对象初始化完毕。 

(8)将对象的内存地址赋值给p变量,让p变量指向该对象。 

11、static关键字: 

(1)静态的意思,用来修饰成员变量和成员函数 

(2)静态的特点: 

随着类的加载而加载 

优先于对象存在 

对所有对象共享 

可以被类名直接调用 

(3)静态的注意事项 

A:静态方法只能访问静态成员 

为什么:因为静态的内容是随着类的加载而加载,它是先进内存的。 

B:静态方法中不能使用this,super关键字 

C:主方法是静态的 

public static void main(String[] args) 

public:公共的意思,是最大权限修饰符。 

static:由于jvm调用main方法的时候,没有创建对象。 

只能通过类名调用。所以,main必须用static修饰。 

void:由于main方法是被jvm调用,不需要返回值。用void修饰。 

main:main是主要的意思,所以jvm采用了这个名字。是程序的入口。

String[]:字符串数组 

args:数组名

在运行的时候,通过java命令给args数组赋值。 

格式:java MainTest hello world itcast 

(4)静态变量和成员变量的区别 

A:调用方式 

静态变量也称为类变量,可以直接通过类名调用。也可以通过对象名调用。 

这个变量属于类。 

成员变量也称为实例变量,只能通过对象名调用。这个变量属于对象。 

B:存储位置 

静态变量存储在方法区长中的静态区。 

成员变量存储在堆内存。 

C:生命周期 

静态变量随着类的加载而存在,随着类的消失而消失。生命周期长。 

成员变量随着对象的创建而存在,随着对象的消失而消失。 

D:与对象的相关性 

静态变量是所有对象共享的数据。 

成员变量是每个对象所特有的数据。 

(5)静态的优点和弊端 

优点: 

对对象的共享数据进行单独空间的存储,节省内存,没有必要每个对象都存储一份 

可直接被类名调用 

弊端: 

生命周期过长,随着类的消失而消失 

访问出现权限,即静态虽好但只能访问静态 

(6)什么使用使用静态呢? 

A:当所有对象共享某个数据的时候,就把这个成员变量定义为静态修饰的。 

B:当某个方法没有访问该类中的非静态成员,就可以把这个方法定义为静态修饰。

静态的生命周期比较长,所以一般不推荐使用。 

(7)静态代码块 

A:它只执行一次,它比main还先执行。 

B:执行顺序 

静态代码块–构造代码块–构造方法

12、制作API(次重点) 

API(全拼):Application Program Interface 应用程序编程接口。 

(1)类中的内容需要用文档注释。 

(2)使用JDK\bin目录下的javadoc工具。 

格式:javadoc -d 目录 -author -version ArrayTool.java 

13、单例设计模式: 

(1)设计模式: 

解决某类问题行之有效的方法,是一种思想,是规律的总结 

(2)用来保证某个类在内存中只有一个对象 

(3)保证唯一性的思想及步骤 

**为了避免其他程序建立该类对象,先禁止其他程序建立该类对象,即将构造函数私有化 

**为了其他程序访问到该类对象,须在本类中创建一个该类私有对象 

**为了方便其他程序访问到该类对象,可对外提供一个公共访问方式

比如API中的Runtime类就是单例设计模式。

(4)单例设计模式的两种方式 

A:饿汉式 当类加载的时候,就创建对象。

class Student

        {

            private Student(){}

            private static final Student s = new Student();

            public static Student getInstance()

            {

                return s;

            }

        }

B:懒汉式 当使用的使用,才去创建对象。

class Student

        {

            private Student(){}

            private static final Student s = null;

            public static Student getInstance()

            {

                if(s==null)

                {

                    //线程1就进来了,线程2就进来了。                   

                    s = new Student();

                }

                return s;

            }

        }

饿汉式和懒汉式** 

是类一加载进内存就创建好了对象; 

懒汉式则是类才加载进内存的时候,对象还没有存在,只有调用了getInstance()方法时, 

对象才开始创建。 

** 

懒汉式是延迟加载,如果多个线程同时操作懒汉式时就有可能出现线程安全问题,解决线程安全问题 

可以加同步来解决。但是加了同步之后,每一次都要比较锁,效率就变慢了, 

所以可以加双重判断来提高程序效率。 

注:开发常用饿汉式,因为饿汉式简单安全。懒汉式多线程的时候容易发生问题

14、Math类的使用(重点) 

(1)数学操作类:该类没有构造函数,方法均为静态的 

(2)掌握内容 

A:成员变量 

**E:比任何其他值都更接近e(即自然对数的底数)的double值。 

**PI:比任何其他值都更接近pi(即圆的周长与直径之比)的double值。 

B:成员方法 

**static double abs(double a) 

返回 double 值的绝对值。返回绝对值 

**static double ceil(double a) 

返回最小的(最接近负无穷大)double 值,该值大于等于参数,并等于某个整数。 

**static double floor(double a) 

返回最大的(最接近正无穷大)double 值,该值小于等于参数,并等于某个整数。 

**max:返回两个值中较大的那个 

**min:返回两个值中较小的那个 

**static long round(double a) 返回最接近参数的 long。 

static int round(float a) 返回最接近参数的 int。 

**static double random() 

返回带正号的 double 值,该值大于等于 0.0 且小于 1.0。 

**static double pow(double a, double b) 

返回第一个参数的第二个参数次幂的值。 

**static double sqrt(double a) 

返回正确舍入的 double 值的正平方根。 

15、Random类的使用(重点) 

(1)产生随机数的类 

(2)掌握内容 

A:构造方法 

**Random() 创建一个新的随机数生成器。 

**Random(long seed) 使用单个 long 种子创建一个新的随机数生成器。 

B:成员方法 

**int nextInt() 返回下一个伪随机数,它是此随机数生成器的序列中均匀分布的 int 值。 

**int nextInt(int n) 返回一个伪随机数,它是取自此随机数生成器序列的、 

在 0(包括)和指定值(不包括)之间均匀分布的 int 值。 

16、Scanner类的使用 

(1)可以获取从键盘的输入数据 

(2)掌握内容 

构造方法: 

Scanner(InputStream source) 构造一个新的 Scanner,它生成的值是从指定的输入流扫描的。 

如:Scanner sc = new Scanner(System.in); 

方法摘要 

sc.nextInt();获取整型数据 

sc.nextLine();获取字符串数据 

17、继承(重点) 

(1)把很多类的相同特征和行为进行抽取,用一个类来描述。让多个类和这个类产生一个关系。 

这样的话,多个类就可以省略很多代码。这个关系就是继承。java中用extends关键字表示。 

(2)继承的体系结构 

A:多个具体的对象,不断的向上抽取共享的内容,最终形成了一个体系。这个体系叫做继承体系。 

B:继承体系的学习和使用原则 

**学习顶层的内容。因为他是整个体系的共性内容。 

**创建子类使用。也就是使用底层的具体对象。 

(3)继承的特点: 

A:java中只能单继承,没有多继承。 

B:java可以有多重(层)继承。 

(4)继承的好处: 

继承的出现提高了代码的复用性。 

继承的出现让类与类之间产生了关系,提供了多态的前提。 

(5)子父类中的成员关系 

A:成员变量 

在子类方法中使用一个变量时: 

首先,在方法的局部变量中找这个变量,有则使用。 

否则,在本类中找成员变量,有则使用。 

否则,在父类中找成员变量,有则使用。 

否则,报错。 

B:成员方法 

用子类对象使用一个方法时。 

首先,在子类中找这个方法,有则使用。 

否则,在父类中找这个方法,有则使用。 

否则,报错。

重写和重载的区别? 

重载:在同一类中。方法名相同,参数列表不同。重载可以改变返回类型。 

重写:在不同类中(子父类中)。 

方法声明相同(返回类型,方法名,参数列表均相同)。 

重写需要注意: 

**子类方法的访问权限要大于等于父类方法的访问权限。 

**静态只能重写静态。但是这种情况一般不会出现。

构造方法 

**子类的实例化过程 

*子类创建对象时,会先去创建父类的对象。 

默认是去调用父类的无参构造方法。 

*子类构造方法中,第一行默认是super() 

*为什么子类中第一行会默认有super() 

因为他继承父类的成员使用,使用前这些成员必须初始化, 

而他们是父类的成员,所以,必须通过父类进行初始化。 

所以,会先创建一个父类的对象。 

**当父类没有无参构造方法时 

必须使用this或者super调用其他的构造方法。 

(6)this和super的区别 

this:代表本类对象的引用。 

super:代表父类的存储空间。

18、final关键字(重点) 

(1)最终的意思,可以用于修饰类,方法,变量。 

(2)final修饰的类不能被继承。 

final修饰的方法不能被重写。 

final修饰的变量是一个常量。只能被赋值一次。 

内部类只能访问被final修饰的局部变量。

19、抽象类(重点) 

(1)多个类有相同的方法声明,但是方法体不一样。这个时候,我们考虑把方法声明进行抽取。 

让子类继承后,自己去实现方法体。没有方法体的方法,我们需要用抽象标志下。 

抽象的关键字是:abstract。 

(2)抽象类: 

该方法称为抽象方法,包含抽象方法的类就是抽象类。 

(3)抽象类的特点: 

A:抽象类和抽象方法都要用abstract进行修饰 

B:抽象类不能被实例化 

C:抽象类中不一定有抽象方法,但是,有抽象方法的类一定是抽象类。 

(4)抽象类中数据的特点 

A:成员变量 

抽象类中可以有变量,也可以有常量。 

B:成员方法 

抽象类中可以有抽象方法,也可以有非抽象方法。 

C:构造方法 

抽象类是一个类,所以,它有构造方法。 

虽然本身不能实例化。但是可以给子类实例化使用。 

(5)抽象类中的问题 

A:抽象类中是否有构造方法?能不能被实例化?如果不能,为什么有构造方法? 

抽象类有构造方法。 

抽象类不能被实例化。 

抽象类中的构造方法供子类实例化调用。 

B:抽象关键字abstract不可以和哪些关键字共存? 

**private: 

私有内容子类继承不到,所以,不能重写。 

但是abstract修饰的方法,要求被重写。两者冲突。 

**final 

final修饰的方法不能被重写。 

而abstract修饰的方法,要求被重写。两者冲突。 

**static 

假如一个抽象方法能通过static修饰,那么这个方法,就可以直接通过类名调用。 

而抽象方法是没有方法体的,这样的调用无意义。所以,不能用static修饰。 

C:抽象类中可不可以没有抽象方法?如果可以,这样的类有什么用吗? 

抽象类可以没有抽象方法。

20、接口interface 

(1)当一个类中的方法都是抽象的时候,java提供了另一种表示方式,叫接口。 

用interface关键字表示。类与接口关系用implements表示。 

(2)接口的成员特点 

A:成员变量 

是常量,默认修饰 public static final 

B:成员方法 

都是抽象的,默认修饰 public abstract 

(3)关系 

A:类与类的关系 

是继承关系。类与类只能单继承,可以多重继承。 

B:类和接口的关系 

是实现关系。类可以多实现接口。 

类在继承一个类的同时,可以实现多个接口。 

C:接口和接口的关系 

是继承关系。接口可以多继承接口。 

(4)接口的特点 

A:是对外暴露的规则 

B:是功能的扩展 

C:接口的出现降低耦合性。 

耦合(类与类之间的关系) 

内聚(类完成功能的能力) 

编程规范:低耦合,高内聚。 

D:接口可以多实现。如:CPU和主板、笔记本的USB插口、插座 

(5)接口和抽象类的区别 

A:抽象类只能被单继承 

接口可以多实现,接口的出现避免了多继承的局限性。 

B:抽象类中的数据特点: 

成员变量:可以是变量,也可以是常量 

成员方法:可以是抽象方法,也可以是非抽象方法 

构造方法:有构造方法 

接口中的数据特点: 

成员变量:是常量。默认修饰 public static final 

成员方法:都是抽象方法。都有默认修饰 public abstract 

构造方法:没有构造方法 

C:抽象类中定义的是继承体系中的共性功能。 

接口中定义的是继承体系中的扩展功能。 

D:抽象类被继承是”is a”关系:xx是yy的一种 

接口被实现是”like a”关系:xx像yy的一种

21、多态: 

(1)同一个对象,在程序不同时刻的多种运行状态。举例:动物,狗是狗,狗是动物。水(气态,液态,固态) 

(2)多态前提 

A:存在着继承或者实现关系 

B:有方法的重写 

C:父类(接口)引用指向子类(实现)对象 

(3)多态的好处和弊端: 

好处:多态的存在提高了程序的扩展性和后期可维护性 

弊端:虽然可以预先使用,但是只能访问父类中已有的功能,运行的是后期子类的功能内容。 

不能预先使用子类中定义的特有功能。 

(4)多态中对象调用成员的特点 

Fu f = new Zi(); 

A:成员变量 

编译看左边,运行看左边 

B:成员方法 

编译看左边,运行看右边 

C:静态方法 

编译看左边,运行看左边 

(5)多态的思想 

指挥同一批对象做事情。举例:带兵打仗,下课等。

22、instanceof关键字 

A:用于判断某个对象是否是某种类型。 

B:格式 

对象名 instanceof 子类(实现)名

23、Object类: 

(1)是所有类的根类,超类。 

java中提供的类以及我们自定义的类都直接或者间接的继承自Object类。 

(2)Object类中的方法 

A:void finalize() 

当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。 

B:Class getClass() 

获取对象的字节码文件的描述类,后面再讲反射的时候还会在说这个类。 

String name = s.getClass().getName(); 

C:int hashCode() 

获取对象的哈希值。其实就是对象的内存地址值十进制表示 

D:String toString() 

返回对象的字符串表示。 

表示格式: 

getClass().getName()+”@”+Integer.toHexString(hashCode());

一般我们输出对象名的时候,其实底层调用的就是该对象的toString()方法。

这种返回没有意义,所以,我们会重写这个方法,显示类的成员变量信息。 

E:boolean equals(Object obj) 

用于比较两个对象的地址值是否相同。 

我们获取对象后,比较它的地址值意义不大。所以也会对这个方法进行重写。 

重写要完成什么功能,是根据需求定的。 

(3)==和equals的用法: 

A:==怎么用? 

**可以用于比较基本数据类型,比较的就是基本数据类型的值是否相等。 

**可以用于比较引用数据类型,比较的是对象的地址值是否相等。 

B:equals怎么用? 

equals只能用于比较引用数据类型的。 

**Object提供的equals是用于比较对象地址值是否相同。 

**自定义类中,如果重写了equals方法,那么就是按照你自己的需求来比较的。

24、package关键字 

(1)包:其实就是文件夹。用于区分不同包下相同的类名。 

(2)好处: 

A:对类文件进行分类管理。 

B:给类提供了多层命名空间 

aaa.Demo 

bbb.Demo 

C:写在程序文件的第一行。 

D:包也是一种封装形式。

25、import关键字 

(1)导入包的关键字 

(2)格式: 

import 包名; 

(3)注意: 

A:一个程序文件中只有一个package,可以有多个import。 

B:用来导包中的类,不导入包中的包。 

C:通常写import mypack.Demo,明确自己使用的类。 

(4)关键字的顺序 

类,包,导包这些关键的顺序。 

包 – > 到包 – > 类

26、不同修饰符可以修饰哪些内容 

一般格式:

    成员变量:

    权限修饰符+static/final+数据类型+成员变量名

    public static final int NUM = 10;

    成员方法:

    权限修饰符+static/final/abstract+返回类型+方法名

27、内部类(次重点) 

(1)把一个类定义在某个类中的,这个类就被称为内部类,内置类,嵌套类。 

(2)访问特点: 

A:内部类可以直接访问外部类中的成员,因为内部类持有外部类的引用, 

格式为:外部类名.this 

B:外部类要想访问内部类的成员,必须创建对象访问。 

(3)内部类的访问格式: 

A:当内部类定义在外部类的成员位置,而且非私有,则可以在其他外部类中直接建立内部类对象 

格式:外部类名.内部类名 变量名 = new 外部类对象.内部类对象 

如:Outer.Inner in = new Outer().new Inner() 

B:当内部类在外部类成员位置,且被static修饰时 

**外部其他类可直接访问静态内部类的非静态成员 

格式:new 外部类名.内部类名().内部类成员 

如:new Outer.Inner().function(); 

**外部其他类可直接访问静态内部类的静态成员 

格式:new 外部类名.内部类名.内部类成员 

如:new Outer.Inner.function(); 

(4)什么使用时候内部类呢? 

假如有A类和B类,A类想直接访问B类的成员,B类访问A类成员的时候, 

需要创建A类对象进行访问,这个时候,就可以把A类定义为B类的内部类。 

(5)内部类的位置 

A:成员位置 

**可以被private修饰(Body,Heart) 

**可以被static修饰。(它访问的外部类的成员必须是静态的) 

B:局部位置 

**可以直接访问外部类中的成员,因为还持有外部类的持用 

也可以直接访问局部成员,但是局部成员要用final修饰。 

注意:局部内部类不能用private和static修饰 

(6)通过class文件我们就可以区分是否带有内部类,以及内部类的位置 

OuterInner:成员内部类OuterInner:成员内部类Outer1Inner:局部内部类

28、匿名内部类(局部内部类的简写) (重点) 

(1)前提:继承一个类或者实现一个接口 

(注意不要弄混匿名内部类的前提和多态的前提) 

(2)格式: 

new 父类名或者接口名() 

重写父类方法或者实现接口中的方法。 

也可以自定义其他方法。 

}; 

(3)什么时候定义匿名内部类? 

匿名内部类只是为了简化书写,匿名内部类有局限,通常定义匿名内部类时,该类方法不超过3个 

(4)匿名内部类的好处和弊端: 

好处:简化代码书写 

弊端: 

不能直接调用自己的特有方法 

不能执行强转换动作 

如果该类里面方法较多,不允许使用匿名内部类

29、模板设计模式: 

在定义功能时,功能的一部分是确定的,有一部分是不确定的,而且确定的部分在使用不确定的部分, 

可将不确定的部分暴露出去,由该类的子类去完成。 

如:求一段程序的运行时间例子。

30、异常 

(1)程序运行过程中的不正常现象就叫异常。 

(2)导致程序运行不正常的现象有很多,所以,就有很多的异常对象。 

而这些异常对象存在着共性的内容,所以,可以不断的进行抽取。最终形成了异常的体系结构。 

异常体系的根类是:Throwable 

Throwable: 

|–Error:重大的问题,我们处理不了。也不需要编写代码处理。比如说内存溢出。 

|–Exception:一般性的错误,是需要我们编写代码进行处理的。 

|–RuntimeException:运行时异常,这个我们也不需要处理。 

其实就是为了让他在运行时出问题,然后我们回来修改代码。 

(3)异常的分类 

异常有两种: 

编译时被检测异常: 

该异常在编译时,如果没有处理(没有抛也没有try),编译失败。 

该异常被标识,代表这可以被处理。 

运行时异常(编译时不检测) 

在编译时,不需要处理,编译器不检查。 

该异常的发生,建议不处理,让程序停止。需要对代码进行修正。 

(4)异常体系的特点: 

异常体系中的所有类及其子类对象都具备可抛性。也就是说可以被throw和throws关键字所操作。 

(5)main方法是如何处理异常的。 

A:在main里面编写代码进行处理 

B:交给jvm自己进行处理。采用的是jvm的默认处理方式。 

其实就是相当于调用了异常对象的printStackTrace()方法。 

(6)Throwable类的学习 

getMessage():获取异常信息,返回字符串。 

toString():获取异常类名和异常信息,返回字符串。 

printStackTrace():获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。 

(7)异常的处理· 

A:try…catch…finally 

基本格式: 

try 

可能出现异常的代码 

catch(异常对象) 

异常处理代码 

finally 

释放资源 

}

变形格式:

        try...catch

        try...catch...catch...

        try...catch...catch...finally

    **多个异常同时被捕获的时候,记住一个原则:

        先逮小的,再逮大的。

    **finally:永远被执行,除非退出jvm。System.exit(0);

        面试题2个。

        ***:final,finally,finalize区别。

          final是最终的意思。它可以用于修饰类,成员变量,成员方法。

          它修饰的类不能被继承,它修饰的变量时常量,它修饰的方法不能被重写。

          finally:是异常处理里面的关键字。

          它其中的代码永远被执行。特殊情况:在执行它之前jvm退出。System.exit(0);

          finalize:是Object类中的一个方法。

          它是于垃圾回收器调用的方式。

        ***:假如catch中有return语句, finally里中的代码会执行吗?

          是在return前,还是在return后呢?

          会,在return前执行finally里面的代码。

(8)Exception和RuntimeException的区别

    A:Exception:一般性的错误,是需要我们编写代码进行处理的。 

    B:RuntimeException:运行时异常,这个我们也不需要处理。

                  其实就是为了让他在运行时出问题,然后我们回来修改代码。

        在用throws抛出一个的时候,如果这个异常是属于RuntimeException的体系的时候,

        我们在调用的地方可以不用处理。(RuntimeException和RuntimeException的子类)

        在用throws抛出一个的时候,如果这个异常是属于Exception的体系的时候,

        我们在调用的地方必须进行处理或者继续抛出。

(9)自定义异常

    定义类继承Exception或者RuntimeException

    1,为了让该自定义类具备可抛性。

    2,让该类具备操作异常的共性方法。

class MyExcepiton extends Exception{ 

            MyExcepiton(){}

            MyExcepiton(String message)

            {

                super(message);

            }

        }

        class MyException extends RuntimeException{         

           MyExcepiton(){}           

        MyExcepiton(String message)

            {

                super(message);

            }

        }

(10)throws和throw的区别

    A:有throws的时候可以没有throw。

      有throw的时候,如果throw抛的异常是Exception体系,那么必须有throws在方法上声明。

    B:throws用于方法的声明上,其后跟的是异常类名,后面可以跟多个异常类,之间用逗号隔开

      throw用于方法体中,其后跟的是一个异常对象名

三、多线程:


1、进程和线程: 

进程:正在进行的程序。每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元。 

线程:进程内部的一条执行路径或者一个控制单元。 

两者的区别: 

一个进程至少有一个线程 

进程在执行过程中拥有独立的内存单元,而多个线程共享内存; 

2、jvm多线程的启动是多线程吗? 

java的虚拟机jvm启动的是单线程,就有发生内存泄露的可能,而我们使用java程序没出现这样的问题, 

也就是jvm启动至少有两个线程,一个执行java程序,一个执行垃圾回收。所以是多线程。

3、多线程的优势: 

解决了多部分同时运行的问题,提高效率 

4、线程的弊端: 

线程太多会导致效率的降低,因为线程的执行依靠的是CPU的来回切换。 

5、什么叫多线程: 

一个进程中有多个线程,称为多线程。 

6、实现多线程的方法: 

实现多线程可以通过继承Thread类和实现Runnable接口。 

(1)继承Thread 

定义一个类继承Thread类 

复写Thread类中的public void run()方法,将线程的任务代码封装到run方法中 

直接创建Thread的子类对象,创建线程 

调用start()方法,开启线程(调用线程的任务run方法) 

//另外可以通过Thread的getName()获取线程的名称。

(2)实现Runnable接口;

    定义一个类,实现Runnable接口;

    覆盖接口的public void run()的方法,将线程的任务代码封装到run方法中;

    创建Runnable接口的子类对象

    将Runnabl接口的子类对象作为参数传递给Thread类的构造函数,创建Thread类对象

  (原因:线程的任务都封装在Runnable接口子类对象的run方法中。

    所以要在线程对象创建时就必须明确要运行的任务)。

    调用start()方法,启动线程。

两种方法区别:

    (1)实现Runnable接口避免了单继承的局限性

    (2)继承Thread类线程代码存放在Thread子类的run方法中

      实现Runnable接口线程代码存放在接口的子类的run方法中;

      在定义线程时,建议使用实现Runnable接口,因为几乎所有多线程都可以使用这种方式实现

7、创建线程是为什么要复写run方法? 

Thread类用于描述线程。Thread类定义了一个功能,用于存储线程要运行的代码,该存储功能就是run方法。

8、start()和run方法有什么区别? 

调用start方法方可启动线程,而run方法只是thread的一个普通方法,调用run方法不能实现多线程; 

Start()方法: 

start方法用来启动线程,实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的 

代码。通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行, 

一旦得到cpu时间片(执行权),就开始执行run()方法,这里方法run()称为线程体, 

它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。 

Run()方法: 

run()方法只是Thread类的一个普通方法,如果直接调用Run方法,程序中依然只有主线程这一个线程, 

其程序执行路径还是只有一条,还是要等待run方法体执行完毕后才可继续执行下面的代码, 

这样就没有达到多线程的目的。 

9、线程的几种状态: 

新建:new一个Thread对象或者其子类对象就是创建一个线程,当一个线程对象被创建,但是没有开启,这个时候, 

只是对象线程对象开辟了内存空间和初始化数据。 

就绪:新建的对象调用start方法,就开启了线程,线程就到了就绪状态。 

在这个状态的线程对象,具有执行资格,没有执行权。 

运行:当线程对象获取到了CPU的资源。 

在这个状态的线程对象,既有执行资格,也有执行权。 

冻结:运行过程中的线程由于某些原因(比如wait,sleep),释放了执行资格和执行权。 

当然,他们可以回到运行状态。只不过,不是直接回到。 

而是先回到就绪状态。 

死亡:当线程对象调用的run方法结束,或者直接调用stop方法,就让线程对象死亡,在内存中变成了垃圾

10、sleep()和wait()的区别: 

(1)这两个方法来自不同的类,sleep()来自Thread类,和wait()来自Object类。 

(2)sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线程里调用了b的sleep方法,实际上还是a去睡觉, 

要让b线程睡觉要在b的代码中调用sleep。而wait()是Object类的非静态方法 

(3)sleep()释放资源不释放锁,而wait()释放资源释放锁; 

(4)使用范围:wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用

11、多线程安全问题: 

(1)原因:当程序的多条语句在操作线程共享数据时(如买票例子中的票就是共享资源),由于线程的随机性导致 

一个线程对多条语句,执行了一部分还没执行完,另一个线程抢夺到cpu执行权参与进来执行, 

此时就导致共享数据发生错误。比如买票例子中打印重票和错票的情况。 

(2)解决方法:对多条操作共享数据的语句进行同步,一个线程在执行过程中其他线程不可以参与进来 

12、Java中多线程同步是什么? 

同步是用来解决多线程的安全问题的,在多线程中,同步能控制对共享数据的访问。如果没有同步,当一个线程在 

修改一个共享数据时,而另外一个线程正在使用或者更新同一个共享数据,这样容易导致程序出现错误的结果。 

13、什么是锁?锁的作用是什么? 

锁就是对象 

锁的作用是保证线程同步,解决线程安全问题。 

持有锁的线程可以在同步中执行,没有锁的线程即使获得cpu执行权,也进不去。

14、同步的前提: 

(1)必须保证有两个以上线程 

(2)必须是多个线程使用同一个锁,即多条语句在操作线程共享数据 

(3)必须保证同步中只有一个线程在运行 

15、同步的好处和弊端 

好处:同步解决了多线程的安全问题 

弊端:多线程都需要判断锁,比较消耗资源 

16、同步的两种表现形式: 

(1)同步代码块: 

可以指定需要获取哪个对象的同步锁,使用synchronized的代码块同样需要锁,但他的锁可以是任意对象 

考虑到安全问题,一般还是使用同一个对象,相对来说效率较高。

注意:

    **虽然同步代码快的锁可以使任何对象,但是在进行多线程通信使用同步代码快时,

      必须保证同步代码快的锁的对象和,否则会报错。

    **同步函数的锁是this,也要保证同步函数的锁的对象和调用wait、notify和notifyAll的对象是

      同一个对象,也就是都是this锁代表的对象。

    格式:

    synchronized(对象)

    {

        需同步的代码;

    }

(2)同步函数

    同步方法是指进入该方法时需要获取this对象的同步锁,在方法上使用synchronized关键字,

    使用this对象作为锁,也就是使用了当前对象,因为锁住了方法,所以相对于代码块来说效率相对较低。

    注:静态同步函数的锁是该方法所在的类的字节码文件对象,即类名.class文件

    格式:

    修饰词 synchronized 返回值类型 函数名(参数列表)

    {

        需同步的代码;

    }

在jdk1.5后,用lock锁取代了synchronized,个人理解也就是对同步代码块做了修改,

并没有提供对同步方法的修改,主要还是效率问题吧。

17、多线程的单例设计模式:保证某个类中内存中只有一个对象 

(1)饿汉式:

class Single

        {

            private Single(){}//将构造函数私有化,不让别的类建立该类对象            private static final Single s=new Single();//自己建立一个对象            public static Single getInstance()//提供一个公共访问方式

            {

                return s;

            }

        }

(2)懒汉式:

class Single

        {

            private Single(){}

            private static Single s;

            public static Single getInstance()

            {

                if(s==null)

                    s=new Single();

                return s;

            }

        }

饿汉式和懒汉式的区别:

    **

    饿汉式是类一加载进内存就创建好了对象;

    懒汉式则是类加载进内存的时候,对象还没有存在,只有调用了getInstance()方法时,对象才开始创建。 

    **

    懒汉式是延迟加载,如果多个线程同时操作懒汉式时就有可能出现线程安全问题,解决线程安全问题

    可以加同步来解决。但是加了同步之后,每一次都要比较锁,效率就变慢了,

    所以可以加双重判断来提高程序效率。

    如将上述懒汉式的Instance函数改成同步:

public static Single getInstance()

        {

            if(s==null)

            {

                synchronized(Single.class)

                {

                    if(s==null)

                        s=new Single();

                }

            }

            return s;

        }

18、死锁 

两个线程对两个同步对象具有循环依赖时,就会发生死锁。即同步嵌套同步,而锁却不同。 

19、wait()、sleep()、notify()、notifyAll() 

wait():使一个线程处于等待状态,并且释放所持有的对象的lock。 

sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。 

notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程, 

而是由JVM确定唤醒哪个线程(一般是最先开始等待的线程),而且不是按优先级。 

Allnotity():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。 

20、为什么wait()、notify()、notifyAll()这些用来操作线程的方法定义在Object类中? 

(1)这些方法只存在于同步中; 

(2)使用这些方法时必须要指定所属的锁,即被哪个锁调用这些方法; 

(3)而锁可以是任意对象,所以任意对象调用的方法就定义在Object中。 

21、多线程间通讯: 

多线程间通讯就是多个线程在操作同一资源,但是操作的动作不同. 

(1)为什么要通信 

多线程并发执行的时候, 如果需要指定线程等待或者唤醒指定线程, 那么就需要通信.比如生产者消费者的问题, 

生产一个消费一个,生产的时候需要负责消费的进程等待,生产一个后完成后需要唤醒负责消费的线程, 

同时让自己处于等待,消费的时候负责消费的线程被唤醒,消费完生产的产品后又将等待的生产线程唤醒, 

然后使自己线程处于等待。这样来回通信,以达到生产一个消费一个的目的。 

(2)怎么通信 

在同步代码块中, 使用锁对象的wait()方法可以让当前线程等待, 直到有其他线程唤醒为止. 

使用锁对象的notify()方法可以唤醒一个等待的线程,或者notifyAll唤醒所有等待的线程. 

多线程间通信用sleep很难实现,睡眠时间很难把握。

22、Lock和Condition 

实现提供比synchronized方法和语句可获得的更广泛的锁的操作,可支持多个相关的Condition对象 

Lock是个接口 

锁是控制多个线程对共享数据进行访问的工具。

JDK1.5中提供了多线程升级的解决方案:

将同步synchonized替换成了显示的Lock操作,将Object中的wait、notify、notifyAll替换成了Condition对象。

该对象可以Lock锁进行获取

Lock的方法摘要:

    void lock()  获取锁。

    Condition newCondition() 返回绑定到此 Lock 实例的新 Condition 实例。

    void unlock() 释放锁。

Condition方法摘要:

    void await() 造成当前线程在接到信号或被中断之前一直处于等待状态。

    void signal() 唤醒一个等待线程。         

    void signalAll() 唤醒所有等待线程。

23、停止线程: 

stop方法已经过时,如何停止线程? 

停止线程的方法只有一种,就是run方法结束。如何让run方法结束呢? 

开启多线程运行,运行代码通常是循环体,只要控制住循环,就可以让run方法结束,也就是结束线程。

特殊情况:当线程属于冻结状态,就不会读取循环控制标记,则线程就不会结束。

    为解决该特殊情况,可引入Thread类中的Interrupt方法结束线程的冻结状态;

    当没有指定的方式让冻结线程恢复到运行状态时,需要对冻结进行清除,强制让线程恢复到运行状态

24、interrupt: 

void interrupt() 中断线程: 

中断状态将被清除,它还将收到一个 InterruptedException 

25、守护线程(后台线程) 

setDaemon(boolean on):将该线程标记为守护线程或者用户线程。 

当主线程结束,守护线程自动结束,比如圣斗士星矢里面的守护雅典娜, 

在多线程里面主线程就是雅典娜,守护线程就是圣斗士,主线程结束了, 

守护线程则自动结束。 

当正在运行的线程都是守护线程时,java虚拟机jvm退出;所以该方法必须在启动线程前调用;

守护线程的特点:

    守护线程开启后和前台线程共同抢夺cpu的执行权,开启、运行两者都没区别,

    但结束时有区别,当所有前台线程都结束后,守护线程会自动结束。

26、多线程join方法: 

void join() 等待该线程终止。 

void join(long millis) 等待该线程终止的时间最长为 millis 毫秒。 

throws InterruptedException 

特点:当A线程执行到B线程的join方法时,A就会等待B线程都执行完,A才会执行 

作用: join可以用来临时加入线程执行; 

27、多线程优先级:yield()方法 

yield():暂停当前正在执行的线程对象,并执行其他线程 

setPriority(int newPriority):更改线程优先级 

int getPriority() 返回线程的优先级。 

String toString() 返回该线程的字符串表示形式,包括线程名称、优先级和线程组

(1)MAX_PRIORITY:最高优先级(10级)

(1)Min_PRIORITY:最低优先级(1级)

(1)Morm_PRIORITY:默认优先级(5级)

28、什么是ThreadLocal类,怎么使用它? 

ThreadLocal类提供了线程局部 (thread-local) 变量。是一个线程级别的局部变量,并非“本地线程”。 

ThreadLocal 为每个使用该变量的线程,提供了一个独立的变量副本,每个线程修改副本时不影响其它线程对象的副本

相关文章

网友评论

      本文标题:Java基础知识大全

      本文链接:https://www.haomeiwen.com/subject/kigowftx.html