本篇博客内容只包含极少内容,仅供参考
基本概念
Java 之父:詹姆斯·高斯林
JDK 和 JRE 区别
- JDK:
Java Development Kit
的简称,java 开发工具包,提供了 java 的开发环境和运行环境。 - JRE:
Java Runtime Environment
的简称,java 运行环境,为 java 的运行提供了所需环境。
JDK 包含 JRE 和编译器 javac,还包含很多 java 程序调试和分析的工具。JRE(Java 运行时环境)包含虚拟机但是不包含编译器。
简单来说:如果需要运行 java 程序,只需安装 JRE ,如果需要编写 java 程序,则需要安装 JDK。
Java 安装与配置
Java -version:检测 jdk 是否安装
javac:检测环境变量
环境变量:
- 新建系统变量:
- JAVA_HOME
- jdk 路径,例:C:\Java\jdk1.8.0_241
- 系统变量 path 添加:
- %JAVA_HOME%/bin
- %JAVA_HOME%/jre/bin
Java 语言的特性
- 简单性
- 面向对象
- 分布式
- 健壮性
- 安全性
- 体系结构中立
- 可移植性
- 解释型
- 高性能
- 多线程
- 动态性
基本语言程序结构
基本变量类型
Java 是一种强类型语言。必须为每一个变量声明一种类型。在 Java 中,一共有 8 种基本类型(primitivetype), 其中有 4 种整型(byte,short,int,long)、2 种浮点类型(float,double)、1 种用于表示 Unicode 编码的字符单元的字符类型 char 和 1 种用于表示真值的 boolean 类型。
在 java 中,整形的范围和运行 java 的平台无关,而 c 和 c++和机器有关
字符串
Java 中的基本数据类型只有 8 个,而除了基本数据类型和枚举类型都是引用类型。所以 String 是引用类型。
字符串常用方法
| 方法名 | 代码 | 含义 |
| :———–: | :——————————————–: | :——————————————————————————-: | ——— |
| charAt() | char charAt(int index) | 返回指定索引处的字符 |
| indexOf() | int indexOf(int ch) | 返回与 字符串匹配的第一个子串的位置,从 0 或者 fromIndex 开始,如果不存在,返回-1 |
| replace() | String replace(char oldChar, char newChar) | 用 newChar 替换 oldChar |
| trim() | String trim() | 去除字符串两端空白。 |
| split() | String[] split(String regex[, int limit]) | 用匹配的表达式分割字符串 |
| getBytes() | byte[] getBytes() | 返回字符串的 byte 类型数组。 |
| length() | int length() | 返回字符串长度。 |
| toLowerCase() | String toLowerCase() | 将字符串转成小写字母。 |
| toUpperCase() | String toUpperCase() | 将字符串转成大写字符。 |
| substring() | String s =”hello”.substring(0,3); | 截取字符串 s = “hel” 即从 0 到 2,不包括 3 |
| + | String s = a+b; | 用+拼接字符串 |
| join() | String all = String.join(“/“,”S”,”M”,”L”,”XL”) | all = “S/M/L/XL”; 分隔符连接字符串 |
| equals() | str.equals(str1); | 判断字符串是否相等,不可使用== | indexof() |
字符串是常量,它们的值在创建之后不能更改。StringBuffer,StringBuilder 支持可变的字符串。
空串 “” 和 null
- 空串 “” 是长度为 0 的字符串。可以使用以下代码检查一个字符串是否为空:
if (str.length() == 0) /if (str .equals(""))
- 空串是一个 Java 对象,有自己的串长度(0)和内容(空)。
- null 表示目前没有任何对象与该变量关联,用 str == null 判断。
== 和 equals 区别
==
基本类型和引用类型的 == 作用效果不同,具体如下:
- 基本类型:比较值是否相同
- 引用类型:比较引用(内存地址值)是否相同
示例:
1 | String a = "String"; |
因为 a 和 b 指向一个同一个引用,所以a == b
结果为 true,而 new String()方法重写开辟了内存空间,所以a == c
结果为 false,而 equals 比较的是值,所以结果为 true。
字符串的分配和其他对象分配一样,是需要消耗高昂的时间和空间的,而且字符串我们使用的非常多。JVM 为了提高性能和减少内存的开销,在实例化字符串的时候进行了一些优化:使用字符串常量池。每当我们创建字符串常量时,JVM 会首先检查字符串常量池,如果该字符串已经存在常量池中,那么就直接返回常量池中的实例引用。如果字符串不存在常量池中,就会实例化该字符串并且将其放到常量池中。
由于 String 字符串的不可变性我们可以十分肯定常量池中一定不存在两个相同的字符串。
反而言之,因为需要实现常量池,所以 String 使用 final 修饰,即 String 字符串的不可变。
equals
equals 方法是 Object 类的一个方法,Java 当中所有的类都是继承于 Object 这个超类。equals 本质上就是 ==,比较引用是否相同。只不过 String 和 Integer 等重写了 equals 方法,把它变成了值比较。
JDK1.8 Object 类 equals 方法源码如下,即返回结果取决于两个对象的使用==判断结果。源码如下:
1 | public boolean equals(Object obj) { |
在实际使用中,一般会重写定义的 class 的 equals 方法,如 JDK1.8 java.lang.String 类的 equals 源码如下。即两个字符串使用 == 相等或者两个字符串的所有组成字符都相等返回 true,其他情况返回 false。这里就定义 String 根据 equals 方法判断是否相等的逻辑。
1 | public boolean equals(Object anObject) { |
在之前的例子中,a.equals(b)
和a.equals(c)
比较的是 a 和 b 的值是相同,a 和 c 的值是否相同,所以结果都为 true。
总结
- == 的作用:
- 基本类型:比较值是否相等
- 引用类型:比较内存地址值是否相等
- equals 的作用:
- 引用类型:默认情况下,比较内存地址值是否相等。可以按照需求逻辑,重写对象的 equals 方法。
StringBuffer 和 StirngBuilder
操作字符串的类有:String、StringBuffer、StringBuilder。
String 和 StringBuffer、StringBuilder 的区别在于 String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象,而 StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。
StringBuffer 和 StringBuilder 最大的区别在于,StringBuffer 是线程安全的,而 StringBuilder 是非线程安全的,但 StringBuilder 的性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。
类和对象
类是构造对象的蓝图和模板 ,一个 java 文件可以有无限个类,每个类的权限修饰符只能是 public 或者没有权限修饰符。
- 类中可以创建类
- 方法中不能创建方法
- 方法中可以创建类(不能被外部调用,为方法而存在,只能在方法中调用)
- 方法中的类可以再创建类
- main 不是关键字
匿名内部类企业中不允许新建方法,也不允许创建新属性。
静态属性和方法
每个类中只有一个静态域,所有对象都调用的同一个值,而每个对象都拥有自己的实例域,静态方法不能调用实例,只能调用静态方法。
继承
调用多态对象中的属性时,会调用当前对象的属性值(左侧)
1 | A a = new B(); |
如果 A 类和 B 类同时有 value 这个属性,在获取a的value
时,将隐藏B的value
而返回A的value
。
多态中属性的隐藏
属性的隐藏:在继承中,隐藏的是父类的属性,在多态中,隐藏的是子类的属性值。
类的类型转换,必须保证是某一个父类的对象强转为子类的对象。
多态创建的对象,只拥有当前类型(左侧父类类型)的属性名和对象
当调用属性名的时候,取出的值,是当前对象的值
当调用方法的时候,会检查子类是否重写,如果重写,会调用子类重写的方法
形参只能传当前类型和当前类型的子类类型
自动转换:子类对象赋值给父类类型对象
强制转换:父类类型对象赋值给子类类型对象
多态中的强转,必须存在继承关系
不论是类的继承还是接口的继承,都只能单一继承
类与类,接口和接口之前不能相互继承
包管理
修饰符
java 提供了很多修饰符,主要分为访问修饰符和非访问修饰符两类,修饰符用来定义类、方法或者变量,通常放在语句的最前端。
访问控制修饰符
Java 中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。
- default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
- private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
- public : 对所有类可见。使用对象:类、接口、变量、方法
- protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
非访问修饰符
- static:用于修饰静态方法和静态变量
- final:修饰类,方法和变量
- final 修饰的类叫最终类,该类不能被继承。
- final 修饰的方法不能被重写。
- final 修饰的变量叫常量,常量必须初始化,初始化之后值就不能被修改。
- abstract:创建抽象类和抽象方法
- synchronized 和 volatile:主要用于线程的编程
枚举
public enum size{small,medium,large,extra_large}
枚举类型是一个类,在比较两个枚举类型时,永远不需要调用 equials,直接使用“==”就可以。
所有枚举类型都是 enum 的子类,最有用的是 toString,返回枚举常量名(Size.small.toString()返回字符串”small”
)。
toString 的逆方法是 valueof()( Size s = Enum.valueof(Size.class,”small”)
将 s 设置为 Size.small)。
有一个静态的 values 方法,返回一个包括全部枚举值的数组(Size[] values = Size.values()
)。
ordinal 方法返回位置
反射
JAVA 反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为 Java 语言的反射机制。反射被视为动态语言的关键。
能够分析类能力的程序称为反射。反射机制可以用来
- 在运行时分析类的能力
- 在运行时查看对象
- 实现通用的数组操作代码
- 利用 Method 对象
接口和抽象类
抽象类
抽象类往往用来表征对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。
在 Java 语言中使用 abstract class 来定义抽象类。
1 | public abstract class Employee{ |
抽象方法
Abstract 关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体。
抽象方法的具体实现由它的子类确定,抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。
1 | public abstract class Employee |
抽象类总结
- 抽象类不能被实例化。
- 抽象类不一定要有抽象方法,但是抽象方法必须定义在抽象类中。
- 任何抽象类的子类必须重写父类的抽象方法或者定义自己为抽象类。
- 抽象类不能用 final 修饰,因为抽象类定义出来就是让其他类继承的,用 fianl 修饰就不能被继承,编译器中也会提示错误信息。
- 构造方法,类方法(static 修饰)不能声明为抽象方法
抽象类和普通类的区别:
- 普通类不能包含抽象方法,抽象类可以包含抽象方法。
- 抽象类不能直接实例化,普通类可以直接实例化。
接口的定义和实现
接口是公开的,不能有私有的方法或变量,接口中的所有方法都没有方法体,通过关键字 interface 实现。接口中的所有方法都自动属于 public。
实现
将类声明为实现给定的接口 implement
对接口中的所有方法进行定义
特性
接口不是类,不能使用 new 运算符实例化一个接口,但是能声明接口的变量,接口变量必须引用实现了接口的类对象,接口中的域自动设为public static final
。
jdk8.0 之前接口中只能定义抽象方法,在 jdk8.0 之后可以定义实现方法(加上关键字 default 修饰)
抽象类的定义和实现。
接口和抽象类的区别
接口是对动作的抽象,抽象类是对根源的抽象。
抽象类表示的是,这个对象是什么。接口表示的是,这个对象能做什么。比如,男人,女人,这两个类(如果是类的话……),他们的抽象类是人。说明,他们都是人。
人可以吃东西,狗也可以吃东西,你可以把“吃东西”定义成一个接口,然后让这些类去实现它。
所以,在高级语言上,一个类只能继承一个类(抽象类)(正如人不可能同时是生物和非生物),但是可以实现多个接口(吃饭接口、走路接口)。
举例来自接口和抽象类有什么区别
相同点
- 都不能被实例化
- 接口的实现类或抽象类的子类都只有实现了接口或抽象类中的抽象方法后才能实例化。
不同点
- 接口只有定义,不能有方法的实现,java 1.8 中可以定义 default 方法体,而抽象类可以有定义与实现,方法可在抽象类中实现。
- 实现接口的关键字为 implements,继承抽象类的关键字为 extends。一个类可以实现多个接口,但一个类只能继承一个抽象类。所以,使用接口可以间接地实现多重继承。
- 接口强调特定功能的实现,而抽象类强调所属关系。
- 接口成员变量默认为 public static final,必须赋初值,不能被修改;其所有的成员方法都是 public、abstract 的。抽象类中成员变量默认 default,可在子类中被重新定义,也可被重新赋值;抽象方法被 abstract 修饰,不能被 private、static、synchronized 和 native 等修饰,必须以分号结尾,不带花括号。
- 接口被用于常用的功能,便于日后维护和添加删除,而抽象类更倾向于充当公共类的角色,不适用于日后重新对立面的代码修改。功能需要累积时用抽象类,不需要累积时用接口。
发布与部署
概念
JAR(Java ARchive,Java 归档)是一种与平台无关的文件格式,可将多个文件合成一个文件。
用户可将多个 Java applet 及其所需组件(.class 文件、图像和声音)绑定到 JAR 文件中,而后作为单个的简单 HTTP(Hypertext Tranfer Protocal,超文本传输协议)事务下载到浏览器中,从而大大提高下载速度。
JAR 格式也支持压缩,从而减小了文件的大小,进一步缩短下载时间。另外,applet 编写者也可在 JAR 文件中用数字签名的方式签写各项以确认其来源。
它用 Java 编写,可与现有的 applet 代码完全向后兼容且可充分扩展。
JAR 文件就是 Java Archive File,顾名思意,它的应用是与 Java 息息相关的,是 Java 的一种文档格式。
JAR 文件非常类似 ZIP 文件——准确的说,它就是 ZIP 文件,所以叫它文件包。
JAR 文件与 ZIP 文件唯一的区别就是在 JAR 文件的内容中,包含了一个 META-INF/MANIFEST.MF 文件,这个文件是在生成 JAR 文件的时候自动创建的
Jar 文件是跨平台的
创建 jar
创建一个可执行 JAR 很容易。首先将所有应用程序代码放到一个目录中。假设应用程序中的主类是 com.mycompany.myapp.Sample
。您要创建一个包含应用程序代码的 JAR 文件并标识出主类。为此,在某个位置(不是在应用程序目录中)创建一个名为 manifest 的文件,并在其中加入以下一行:Main-Class: com.mycompany.myapp.Sample
然后,像这样创建 JAR 文件:jar cmf manifest ExecutableJar.jar application-dir
引用 jar
修改 manifest 文件,如果有多个 jar 包需要引用的情况:Class-Path: lib/some.jar lib/some2.jar
每个单独的 jar 用空格隔开就可以了。