Java语言是一种跨平台、适合于分布式计算机环境的面向对象编程语言。它具有以下几个重要特性:
1)简单易学
Java语言去掉了C/C++语言支持的三个不易理解和掌握的数据类型:指针(pointer)、联合体(unions)和结构体(structs),并且C/C++语言中联合体和结构体的功能完全可以在Java语言中用类及类的属性等面向对象的方法来实现,这不但更加合理规范,而且还降低了学习难度。
2)面向对象
Java语言是一种以对象为中心、以消息为驱动的面向对象的编程语言,支持封装、继承和多肽三个概念。
3)平台无关性
平台无关有两种:源代码级和目标代码级。C/C++语言具有一定程度的源代码级平台无关,即用C/C++语言编写的程序不用修改只需编译就可以在不同平台上运行。而Java语言则靠Java虚拟机(JVM-任何一种可以运行Java字节码的软件均可被看成Java的“虚拟机”)在目标代码级实现平台无关性,即一次编译,到处运行。
4)分布式
分布式包括数据分布和操作分布。Java语言支持这两种分布性。Java语言提供了一整套网络类库,开发人员可以利用类库进行网络程序设计,方便地实现Java语言的分布式特性。
5)可靠性
Java解释器运行时实施检查,可以发现数组和字符串访问越界;另外,Java语言提供了异常处理机制,简化错误处理任务,便于恢复。
6)安全性
当Java字节码进入解释器时,首先必须经过字节码检验器的检查;其次,Java解释器将决定程序中类的内存布局;再次,类装载器负责把来自网络的类装载到单独的内存区域,避免应用程序之间相互干扰破坏;最后,客户端用户还可以限制从网络上装载的类只能访问某些文件系统。Java语言综合上述几种机制,成为安全的编程语言。
7)支持多线程
Java语言在两方面支持多线程:一方面,Java环境本身就是多线程的,若干系统线程运行,负责必要的无用单元回收、系统维护等系统级操作;另一方面,Java语言内置多线程机制,可以大大简化多线程应用程序开发。
8) 支持网络编程
Java语言通过它所提供的类库可以处理TCP/IP,用户可以通过URL地址在网络上很方便访问其他对象。
9)编译与解释并存
Java语言的编译器并不是把源文件(.java)编译成二进制,而是将其编译成一种独立于及其平台的字节码文件(.class文件)。字节码文件可以被Java解释器执行,由解释器将字节码文件再翻译成二进制码,使程序得以进行。
1)字节型-byte 2)短整型-short 3)整型-int 4)长整型-long
5)单精度浮点型-float 6)双精度浮点型-double
7)布尔型-boolean
8)字符型-char
不是。java.lang.String 类是 final 类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用 StringBuffer 类。
JAVA 平台提供了两个类:String 和 StringBuffer,它们可以储存和操作字符串,即包含多 个字符的字符数据。
String类 提供了数值不可改变的字符串。
StringBuffer类 提供的字符串进行修改。
当你知道字符数据要改变的时候你就可以使用 StringBuffer 。典型地,你可以会用StringBuffer 来动态构造字符数
StringBuffer 线程安全,StringBuilder 线程不安全。
底层实现上的话,StringBuffer 其实就是比 StringBuilder 多了 Synchronized 修饰。
自动装箱是 Java 编译器在基本数据类型和对应的对象包装类型之间做的一个转化。比如: 把 int 转化成 Integer,double 转化成 Double,等等。
反之就是自动拆箱。
Java 为每个原始类型提供了包装类型:
- 原始类型: boolean,char,byte,short,int,long,float,double
- 包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double
1)抽象
把现实世界中的某一类东西,提取出来,用程序代码表示。
抽象包括两个方面:
a. 数据抽象 -->表示世界中一类事物的特征,就是对象的属性。比如鸟有翅膀,羽毛等(类的属性);
b. 过程抽象 -->表示世界中一类事物的行为,就是对象的行为。比如鸟会飞,会叫(类的方法)
2)封装
把过程和数据包围起来,对数据的访问只能通过已定义的界面。
3)继承
一种联结类的层次模型。
一是子类继承父类,二是类继承接口
4)多态
允许不同类的对象对同一消息做出响应。
重写(子类和父类,同名同参)、重载(同类,同名不同参)和动态链接(对于父类中定义的方法,如果子类中重写了该方法,那么父类型的引用将调用子类中的这个方法,这就是动态链接)。
1)单一职责原则:一个类只做它该做的事情。其核心就是我们常说的"高内聚",写代码最终极的原则只有六个字"高内聚、低耦合",一个对象如果承担太多的职责,那么注定它什么都做不好。
2)开闭原则:软件实体应当对扩展开放,对修改关闭。(在理想的状态下,当我们需要为一个软件系统增加新功能时,只需要从原来的系统派生出一些新类就可以,不需要修改原来的任何一行代码。要做到开闭有两个要点:
①抽象是关键,一个系统中如果没有抽象类或接口系统就没有扩展点;
②封装可变性,将系统中的各种可变因素封装到一个继承结构中,如果多个可变因素混杂在一起,系统将变得复杂而换乱。)
3)依赖倒转原则:面向接口编程。(该原则说得直白和具体一些就是声明方法的参数类型、方法的返回类型、变量的引用类型时,尽可能使用抽象类型而不用具体类型,因为抽象类型可以被它的任何一个子类型所替代,请参考下面的里氏替换原则。)
4)里氏替换原则:任何时候都可以用子类型替换掉父类型。简单的说就是能用父类型的地方就一定能使用子类型。里氏替换原则可以检查继承关系是否合理,如果一个继承关系违背了里氏替换原则,那么这个继承关系一定是错误的,需要对代码进行重构。
需要注意的是:子类一定是增加父类的能力而不是减少父类的能力,因为子类比父类的能力更多,把能力多的对象当成能力少的对象来用当然没有任何问题。
5)接口隔离原则:接口要小而专,绝不能大而全。
6)聚合复用原则:优先使用聚合关系复用代码。(通过继承来复用代码是面向对象程序设计中被滥用得最多的东西,因为所有的教科书都无一例外的对继承进行了鼓吹从而误导了初学者,类与类之间简单的说有三种关系,Is-A关系、Has-A关系、Use-A关系,分别代表继承、关联和依赖。其中,关联关系根据其关联的强度又可以进一步划分为关联、聚合和合成,但说白了都是Has-A关系,合成聚合复用原则想表达的是优先考虑Has-A关系而不是Is-A关系复用代码。例如Properties类继承了Hashtable类,API中原话:因为 Properties继承于 Hashtable,所以可对Properties 对象应用put 和putAll 方法。但不建议使用这两个方法,因为它们允许调用者插入其键或值不是String 的项。相反,应该使用setProperty 方法。这个继承明显就是错误的,更好的做法是在Properties类中放置一个Hashtable类型的成员并且将其键和值都设置为字符串来存储数据。
7)迪米特法则:迪米特法则又叫最少知识原则,一个对象应当对其他对象有尽可能少的了解。(迪米特法则简单的说就是如何做到"低耦合",门面模式和调停者模式就是对迪米特法则的践行。
类是对某一类事物的描述,是抽象的;而对象是一个实实在在的个体,是类的一个实例。比如:“人”是一个类,而“教师”则是“人”的一个实例。
对象是函数、变量的集合体;而类是一组函数和变量的集合体,即类是一组具有相同属性 的对象集合体。
1)抽象类和接口都是用来抽象具体对象的,但是接口的抽象级别最高。
2)抽象类主要用来抽象类别,接口主要用来抽象功能。
3)抽象类要被子类继承,接口要被类实现。
4)抽象类可以有具体的方法和属性,接口只能有抽象方法和不可变常量。
5)接口只能做方法声明,抽象类中可以做方法声明,也可以做方法实现。
6)接口里定义的变量只能是公共的静态常量,抽象类中的变量是普通变量。
7)接口是设计的结果,抽象类是重构的结果。
C++虚类相当于java中的抽象类。
不同之处是:
1)一个子类只能继承一个抽象类(虚类),但能实现多个接口
2)一个抽象类可以有构造方法,接口没有构造方法
3)一个抽象类中的方法不一定是抽象方法,即其中的方法可以有实现(有方法体),接口中的方法都是抽象方法,不能有方法体,只有声明
4)一个抽象类可以是public、private、protected、default,接口只有public
5)一个抽象类中的方法可以是public、private、protected、default,接口中的方法只能是public和default
相同之处是:都不能实例化。
补充说明:接口是一类特殊的抽象类,是更抽象的抽象类,
完全可以。如果不是静态内部类,那没有什么限制。一个内部类对象可以访问创建它的外部类对象的成员包括私有成员。
如果你把静态嵌套类当作内部类的一种特例,那在这种情况下不可以访问外部类的普通成员变量,而只能访问外部类中的静态成员。四种内部类【静态内部类,成员内部类,局部内部类,匿名内部类】:
1)静态内部类:它是用static修饰的,在访问限制上它只能访问外部类中的static所修饰的成员变量或者是方法;
2)成员内部类:成员内部类是最普通的内部类,它可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。
3)局部内部类:局部内部类是定义在外围类的方法中的,在访问的时候它可以直接访问外围类的所有成员!但是不能随便访问局部变量,除非这个局部变量被final修饰。
4)匿名内部类:
a. 匿名内部类其实就是局部内部类的简写格式,只能使用一次。
b. 定义匿名内部类的前提:内部类必须是继承一个类或者实现接口。
c. 匿名内部类的格式: new 父类或者接口(){定义子类的内容}其实匿名内部类就是一个匿名子类对象,可以理解为带内容的对象。
d. 匿名内部类中定义的方法最好不要超过3个。
不能。因为 static 声明的结构随着类的加载而加载,生命周期早于非 static 的变量。 反之,在非 static 的环境中,是可以访问早加载的 static 的变量的。
static 变量在 Java 中是属于类的,它在所有的实例中的值是一样的。当类被 Java 虚拟机载入 的时候,会对 static 变量进行初始化。如果你的代码尝试不用实例来访问非 static 的变量, 编译器会报错,因为这些变量还没有被创建出来,还没有跟任何实例关联上。
某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归, 如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。
使用双亲委派模型的好处在于 Java 类随着它的类加载器一起具备了一种带有优先级的层次 关系。例如类 java.lang.Object,它存在在 rt.jar 中,无论哪一个类加载器要加载这个类,最 终都是委派给处于模型最顶端的 Bootstrap ClassLoader 进行加载,因此 Object 类在程序的各 种类加载器环境中都是同一个类。相反,如果没有双亲委派模型而是由各个类加载器自行加载的 话,如果用户编写了一个 java.lang.Object 的同名类并放在 ClassPath 中,那系统中将会出现多个不同的 Object 类,程序将混乱。因此,如果开发者尝试编写一个与 rt.jar 类库中重名的 Java 类,可以正常编译,但是永远无法被加载运行。
Java 中类不支持多继承,只支持单继承(即一个类只有一个父类)。 但是 java 中的接口 支持多继承,,即一个子接口可以有多个父接口。(接口的作用是用来扩展对象的功能,一个子接口继承多个父接口,说明子接口扩展了多个功能,当类实现接口时,类就扩展了相应的功能)
值传递。Java 编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中 时,参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的。
泛型,即参数化类型——就是将类型由原来的具体的类型参数化, 类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/ 调用时传入具体的类型(类型实参)。
补码的形式。
1)Lambda 表达式 − Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中。
2)方法引用 − 方法引用提供了非常有用的语法,可以直接引用已有 Java 类或对象(实例) 的方法或构造器。与 lambda 联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
3)默认方法 − 默认方法就是一个在接口里面有了一个实现的方法。
4)新工具 − 新的编译工具,如:Nashorn 引擎 jjs、 类依赖分析器 jdeps。
5)Stream API −新添加的 Stream API(java.util.stream) 把真正的函数式编程风格引入到 Java 中。
6)Date Time API − 加强对日期与时间的处理。
7)Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。
8)Nashorn, JavaScript 引擎 − Java 8 提供了一个新的 Nashorn javascript 引擎,它允许 我们在 JVM 上运行特定的 javascript 应用。
优点:1. 简洁。 2. 非常容易并行计算。 3. 可能代表未来的编程趋势。
缺点:1. 若不用并行计算,很多时候计算速度没有比传统的 for 循环快。(并行计算有时 需要预热才显示出效率优势)2. 不容易调试。3. 若其他程序员没有学过 lambda 表达式,代码不容易让其他语言的程序员看懂。