文章目录
1. Java是个啥?
1.1 编程语言发展史
- 第一代:机器语言
- 第二代:汇编语言
- 第三代:高级语言
3.1 面向过程,如C语言
3.2 面向对象:如Java
1.2 Java发展史
- 1991年,SUN(Stanford University Network)-Green项目-James Gosling
- 不同版本JDK说明
`JDK Version 1.1
于1997-02-19发行。
引入的新特性包括:
引入JDBC(Java Database Connectivity);
支持内部类;
引入Java Bean;
引入RMI(Remote Method Invocation);
引入反射(仅用于内省)。
J2SE Version 1.2
开发代号为Playground(操场),于1998-12-08发行。
引入的新特性包括:
引入集合(Collection)框架;
对字符串常量做内存映射;
引入JIT(Just In Time)编译器;
引入对打包的Java文件进行数字签名;
引入控制授权访问系统资源的策略工具;
引入JFC(Java Foundation Classes),包括Swing 1.0、拖放和Java 2D类库;
引入Java 插件;
在JDBC中引入可滚动结果集、BLOB、CLOB、批量更新和用户自定义类型;
在Applet中添加声音支持。
J2SE Version 1.3
开发代号为Kestrel(红隼),于2000-05-08发行。
引入的新特性包括:
引入Java Sound API;
jar文件索引;
对Java的各个方面都做了大量优化和增强。
J2SE Version 1.4
开发代号为Merlin(隼),于2004-02-06发行(首次在JCP下发行)。
引入的新特性包括:
XML处理;
Java打印服务;
引入Logging API;
引入Java Web Start;
引入JDBC 3.0 API;
引入断言;
引入Preferences API;
引入链式异常处理;
支持IPv6;
支持正则表达式;
引入Image I/O slot machine API。
Java Version SE 5.0
开发代号为Tiger(老虎),于2004-09-30发行。
引入的新特性包括:
引入泛型;
增强循环,可以使用迭代方式;
自动装箱与自动拆箱;
类型安全的枚举;
可变参数;
静态引入;
元数据(注解);
引入Instrumentation。
Java Version SE 6
开发代号为Mustang(野马),于2006-12-11发行。
引入的新特性包括:
支持脚本语言;
引入JDBC 4.0 API;
引入Java Compiler API;
可插拔注解;
增加对Native PKI(Public Key Infrastructure)、Java GSS(Generic Security Service)、Kerberos和LDAP(Lightweight Directory Access Protocol)的支持;
继承Web Services;
做了很多优化。
Java Version SE 7
开发代号是Dolphin(海豚),于2011-07-28发行。
引入的新特性包括:
switch语句块中允许以字符串作为分支条件;
在创建泛型对象时应用类型推断;
在一个语句块中捕获多种异常;
支持动态语言;
支持try-with-resources;
引入Java NIO.2开发包;
数值类型可以用2进制字符串表示,并且可以在字符串表示中添加下划线;
钻石型语法;
null值的自动处理。
Java Version SE 8
开发代号是Spider(蜘蛛),于2014-03-18发行。
支持 lambda支持;
增强日期与时间API的功能;
对垃圾回收的性能也进行了改进;
并且移除了permgen区。
Lambdas表达式与Functional接口
接口的默认与静态方法
方法引用
重复注解
更好的类型推测机制
扩展注解的支持`
1.3 Java体系结构
-
JavaSE(Java Standard Edition):标准版,定位在个人计算机上的应用
这个版本是Java平台的核心,它提供了非常丰富的API来开发一般个人计算机上的应用程序,包括用户界面接口AWT及Swing,网络功能与国际化、图像处理能力以及输入输出支持等。在上世纪90年代末互联网上大放异彩的Applet也属于这个版本。Applet后来为Flash取代,Flash即将被HTML5取代。 -
JavaEE(Java Enterprise Edition):企业版,定位在服务器端的应用
JavaEE是JavaSE的扩展,增加了用于服务器开发的类库。如:JDBC是让程序员能直接在Java内使用的SQL的语法来访问数据库内的数据;Servlet能够延伸服务器的功能,通过请求-响应的模式来处理客户端的请求;JSP是一种可以将Java程序代码内嵌在网页内的技术; -
JavaME(Java Micro Edition):微型版,定位在消费性电子产品的应用上
JavaME是JavaSE的内伸,包含J2SE的一部分核心类,也有自己的扩展类,增加了适合微小装置的类库:javax.microedition.io.*等。该版本针对资源有限的电子消费产品的需求精简核心类库,并提供了模块化的架构让不同类型产品能够随时增加支持的能力。
1.4 Java特性和优势
-
跨平台/可移植性
这是Java的核心优势。Java在设计时就很注重移植和跨平台性。比如:Java的int永远都是32位。不像C++可能是16,32,可能是根据编译器厂商规定的变化。这样的话程序的移植就会非常麻烦。 -
安全性
Java适合于网络/分布式环境,为了达到这个目标,在安全性方面投入了很大的精力,使Java可以很容易构建防病毒,防篡改的系统。 -
面向对象
面向对象是一种程序设计技术,非常适合大型软件的设计和开发。由于C++为了照顾大量C语言使用者而兼容了C,使得自身仅仅成为了带类的C语言,多少影响了其面向对象的彻底性!Java则是完全的面向对象语言。 -
简单性
Java就是C++语法的简化版,我们也可以将Java称之为“C+±”。跟我念“C加加减”,指的就是将C++的一些内容去掉;比如:头文件,指针运算,结构,联合,操作符重载,虚基类等等。同时,由于语法基于C语言,因此学习起来完全不费力。 -
高性能
Java最初发展阶段,总是被人诟病“性能低”;客观上,高级语言运行效率总是低于低级语言的,这个无法避免。Java语言本身发展中通过虚拟机的优化提升了几十倍运行效率。比如,通过JIT(JUST IN TIME)即时编译技术提高运行效率。 将一些“热点”字节码编译成本地机器码,并将结果缓存起来,在需要的时候重新调用。这样的话,使Java程序的执行效率大大提高,某些代码甚至接待C++的效率。
因此,Java低性能的短腿,已经被完全解决了。业界发展上,我们也看到很多C++应用转到Java开发,很多C++程序员转型为Java程序员。 -
分布式
Java是为Internet的分布式环境设计的,因为它能够处理TCP/IP协议。事实上,通过URL访问一个网络资源和访问本地文件是一样简单的。Java还支持远程方法调用(RMI,Remote Method Invocation),使程序能够通过网络调用方法。 -
多线程
多线程的使用可以带来更好的交互响应和实时行为。 Java多线程的简单性是Java成为主流服务器端开发语言的主要原因之一。 -
健壮性
Java是一种健壮的语言,吸收了C/C++ 语言的优点,但去掉了其影响程序健壮性的部分(如:指针、内存的申请与释放等)。Java程序不可能造成计算机崩溃。即使Java程序也可能有错误。如果出现某种出乎意料之事,程序也不会崩溃,而是把该异常抛出,再通过异常处理机制加以处理。
1.5 Java核心机制
- 垃圾回收机制
垃圾收集主要是对内存的释放 - 跨平台原理
JVM(Java Virtual Machine)屏蔽了底层运行平台的差别,实现了“一次编译,随处运行”
JDK:Java Development kit ---> JDK是Java开发工具包,其中包括编译工具(javac.exe)打包工具(jar.exe)等,也包括JRE
JRE:Java Runtime Enviroment ---> JRE,即Java运行环境,包含JVM标准实现(Jvm虚拟机)与Java核心类库
JVM:Java Virtual Machine ---> JVM负责将Java字节码解释运行
2. Java基础语法
2.1 关键字
2.2 数据类型
2.3 运算符
2.4 流程控制
- 顺序结构
//if语句
if(布尔表达式1){
语句块1
}else if(布尔表达式2){
语句块2
}else if(布尔表达式n){
语句块n
}else{
语句块n+1
}
// switch多分支结构(多值情况)
switch (表达式) {
case 值1:
语句序列1;
break;
case 值2:
语句序列2;
break;
case 值n:
语句序列n;
break;
......
default:默认语句;
}
- 循环结构
// for循环
for (初始表达式; 布尔表达式; 迭代因子) {
循环体;
}
// while 循环
while (布尔表达式) {
循环体;
}
// do-while循环
do {
循环体;
} while(布尔表达式) ;
2.5 变量与方法的定义
- 变量本质上就是代表一个”可操作的存储空间”,空间位置是确定的,但是里面放置什么值不确定。
type varName [=value][,varName[=value]...]; //[ ]中的内容为可选项,即可有可无
数据类型 变量名 [=初始值] [,变量名 [=初始值]…];
- 方法(method)就是一段用来完成特定功能的代码片段,类似于其它语言的函数(function)。
[修饰符1 修饰符2 …] 返回值类型 方法名(形式参数列表){
Java语句;… … …
}
方法调用方式:
对象名.方法名(实参列表)
方法的详细说明:
形式参数:在方法声明时用于接收外界传入的数据。
实参:调用方法时实际传给方法的数据。
返回值:方法在执行完毕后返还给调用它的环境的数据。
返回值类型:事先约定的返回值的数据类型,如无返回值,必须显示指定为为void
3.面向对象编程(Object Oriented Programming)
3.1 类与对象的关系
- 万事万物皆对象,类是对象向上抽取出相同的部分,对象是类实例化的产物
- 类的创建
public class Person{
// field(属性、成员变量,可以理解为类的名词部分)
// [修饰符] 属性类型 属性名 = [默认值] ;
public String name;
public int age;
// method(方法,可以理解为类的动词部分)
// [修饰符] 方法返回值类型 方法名(形参列表){方法体}
public void eat(){
System.out.println("人会吃饭");
}
}
- 创建对象的过程
Person p = new Person
// 首次要对类进行加载
// 堆中开辟空间
// 对象初始化
// new关键字调用构造器,在构造器中对属性重新进行赋值
3.2 面向对象三大特性
- 封装:就是把类的属性私有化(private修饰),再通过公有方法(public)进行访问和修改
- 继承:如果子类继承了父类,那么子类就可以复用父类的方法和属性,并且可以在此基础上新增方法和属性
- 多态:字面理解,就是多种形态,在Java中,多态指的是,一个类可以有多种表现形态
对多态感兴趣的可以去感受下 宜春大神 link 的烤山药 链接: link - 接口和抽象类:抽象类是单继承,接口是多实现。
- Java动态绑定机制:编译看左,运行看右
class Ye {
String name = "Ye";
public Ye() {
System.out.println(this.name);
}
}
class Fu extends Ye {
String name = "Fu";
public Fu() {
System.out.println(this.name);
}
}
class Son extends Fu {
String name = "Son";
public Son() {
super();//默认调用可省略
System.out.println(this.name);
}
}
public static void main(String[] args) {
Ye ye = new Son();
System.out.println(ye);
}
// 执行结果:
// Ye
// Fu
// Son
// xxx.code01.Son@4554617c
3.3 this,supper,static关键字
- 网上其实有很多关于这三个关键字的解释,但我觉得如果感觉还是有些晦涩难懂,不妨换个角度,先了解Java代码的执行顺序再去尝试理解这三个关键字
- 一般情况下Java代码的执行顺序:开始 --> 父类的静态代码块 --> 子类的静态代码块 --> 父类的普通代码块 --> 父类的构造方法–> 子类的普通代码块 --> 子类的构造方法 --> 结束
- 如果这个角度还不够透彻,我觉得你应该去了解下JVM重要的一个领域——类加载。
3.4 异常
- 异常三连 == “ try-catch-finally”
- throw和throws的区别:
throw:制造异常
throws:方法的声明处声明可能出现的异常
4.注解
4.1 什么是注解?
- 注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
- 注解的作用分类:编写文档,代码分析,编译检查。
- jdk的内置注解
@Override //标记在成员方法上,用于标识当前方法是重写父类(父接口)方法,编译器在对该方法进行编译时会检查是否符合重写规则,如果不符合,编译报错。
@Deprecated // 用于标记当前类、成员变量、成员方法或者构造方法过时如果开发者调用了被标记为过时的方法,编译器在编译期进行警告。
@SuppressWarnings
/*
压制警告注解,可放置在类和方法上,该注解的作用是阻止编译器发出某些警告信息,该注解为单值注解,只有 一个value参数,该参数为字符串数组类型,参数值常用的有如下几个:
unchecked:未检查的转化,如集合没有指定类型还添加元素
unused:未使用的变量
resource:有泛型未指定类型
path:在类路径,原文件路径中有不存在的路径
deprecation:使用了某些不赞成使用的类和方法
fallthrough:switch语句执行到底没有break关键字
rawtypes:没有写泛型,比如: List list = new ArrayList();
all:全部类型的警告
**/
@Repeatable // 表明标记的注解可以多次应用于相同的声明或类型,此注解由Java8版本引入。我们知道注解是不能重复定义的,其实该注解就是一个语法糖,它可以重复多此使用,更适用于我们的特殊场景。
4.2 自定义注解
- 格式 :public @Interface 注解名 {属性列表/无属性} @interface 表示该接口默认继承了Annotation接口
- 注解体中的属性返回值类型:基本数据类型,String类型,枚举类型,注解。不能有void的无返回值类型和以上类型以外的类型。
- 元注解:元注解就是用来描述注解的注解。一般使用元注解来限制自定义注解的使用范围、生命周期等等。
- @Target:指定被修饰的注解的作用范围
属性 | 描述 |
---|---|
CONSTRUCTOR | 用于描述构造器 |
FIELD(常用) | 用于描述属性 |
LOCAL_VARIABLE | 用于描述局部变量 |
METHOD(常用) | 用于描述方法 |
PACKAGE | 用于描述包 |
PARAMETER | 用于描述参数 |
TYPE(常用) | 用于描述类、接口(包括注解类型) 或enum声明 |
ANNOTATION_TYPE | 用于描述注解类型 |
TYPE_USE | 用于描述使用类型 |
- @Retention:指定了被修饰的注解的生命周期
属性 | 描述 |
---|---|
RetentionPolicy.SOURCE | 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。 |
RetentionPolicy.CLASS | 注解只被保留到编译进行时的class文件,但 JVM 加载class文件时候被遗弃,也就是在这个阶段不会读取到该class文件。 |
RetentionPolicy.RUNTIME(常用) | 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。 |
-
@Documented:指定了被修饰的注解是可以Javadoc等工具文档化,就是一个标记注解。被该标记注解标记的注解,生成doc文档时,注解是可以被加载到文档中显示的。
-
@Inherited:指定了被修饰的注解修饰程序元素的时候是可以被子类继承的,该注解也是一个标记注解。而且它也是被文档化的注解。
5. 反射
5.1 什么是反射?
- Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。Java反射机制被称为框架设计的灵魂。
5.2 反射的基本用法
// 学生案例
public class Student extends Person {
private String stName;
private int stAge;
public Student(String stName, int stAge) {
this.stName = stName;
this.stAge = stAge;
System.out.println("有参造方法执行");
}
public Student() {
}
public String getStName() {
return stName;
}
public void setStName(String stName) {
this.stName = stName;
}
public int getStAge() {
return stAge;
}
public void setStAge(int stAge) {
this.stAge = stAge;
}
public void show1(int a) {
System.out.println("show1 invoked! int a = " + a);
}
private int show2(int a) {
System.out.println("show2 invoked! int a = " + a);
return a;
}
@Override
public String toString() {
return "Student{" +
"stName='" + stName + '\'' +
", stAge=" + stAge +
'}';
}
}
- 获取class对象
public class Code09 {
public static void main(String[] args) throws ClassNotFoundException {
Student student = new Student();
Class sc1 = student.getClass();
System.out.println("1.通过getClass()方法获取:" + sc1);
Class sc2 = Student.class;
System.out.println("2.通过内置class属性获取:" + sc2);
Class sc3 = Class.forName("oop.ex.Student");
System.out.println("3.通过Class.forName方法获取:" + sc3);
ClassLoader loader = Code09.class.getClassLoader();
Class sc4 = loader.loadClass("oop.ex.Student");
System.out.println("4.通过类的加载器获取:" + sc4);
// 在运行期间,一个类,只有一个Class对象产生,验证一下
System.out.println(sc1 == sc2);
System.out.println(sc3 == sc4);
System.out.println(sc2 == sc3);
}
}
// 1.通过getClass()方法获取:class oop.ex.Student
// 2.通过内置class属性获取:class oop.ex.Student
// 3.通过Class.forName方法获取:class oop.ex.Student
// 4.通过类的加载器获取:class oop.ex.Student
// true
// true
// true
- 通过反射获取构造方法并使用
- 通过反射获取成员方法并使用
- 通过反射获取成员变量并使用
//获取类的字节码信息
Class clazz = Class.forName("oop.ex.Student");
// 获取所有的构造方法
Constructor[] constructors = clazz.getDeclaredConstructors();
// 获取所有的成员方法
Method[] methods = clazz.getDeclaredMethods();
// 获取所有的成员变量
Field[] fields = clazz.getDeclaredFields();
// 获取有参构造器,传入参数实例化
Constructor c1=clazz.getDeclaredConstructor(String.class,int.class);
Object o1=c1.newInstance("xiaoming",18);
System.out.println(o1);
// 执行结果:有参造方法执行 Student{stName='xiaoming', stAge=18}
Method show1 = clazz.getMethod("show1", int.class);
Object o2 = clazz.getDeclaredConstructor().newInstance();
show1.invoke(o2,18);// 执行结果:show1 invoked! int a = 18
// getMethod不能获取所有方法如private修饰的方法,要使用getDeclaredMethod
Method show2 = clazz.getDeclaredMethod("show2", int.class);
//暴力反射:private修饰的字段需要解除私有限定
show2.setAccessible(true);
Object result = show2.invoke(o2, 18);//执行结果:show2 invoked! int a = 18
System.out.println("show2返回值:"+result);
//执行结果:show2返回值:18
Field stName = clazz.getDeclaredField("stName");
Object o3 = clazz.newInstance();
//暴力反射:private修饰的字段需要解除私有限定
stName.setAccessible(true);
stName.set(o3,"daming");
System.out.println(o3);
// 执行结果:Student{stName='daming', stAge=0}