Java基础入门
距离上一次写System.out.println("Hello World");
已经过去了很长一段时间了,然而学习安卓还是得掌握Java的基础知识,毕竟归根到底Android也只是一个框架而已,因此这里复(yu)习Java的基础知识,主要是通过对比PHP
及JavaScript
来进行整理。
参考:
语言背景
JVM
JVM是Java虚拟机(Java Virtual Machine),可以理解为一个虚构的计算机,最主要的特性就是与平台的无关性:Java的编译程序只需要将源码编译成可以在JVM上运行的目标代码就可以了,而Java程序在不同的平台上运行时不需要重新编译。
JVM是学习Java必须掌握的知识,这个后面慢慢搞明白。
目录结构
Java代码的源文件后缀名为*.java
,Java的代码通过类来进行组织(除了声明和引入包名,其余的代码都必须出现在类中),一个源文件中包含一个或多个类,一个源文件只能导出一个主类(通过public class
声明的那个类,换句话说,public
声明的类必须独立存在于一个源文件中)。
需要注意的是源文件名必须和主类名称相同(否则编译就会出错),我感觉直接从语言方面限制类名是一个很奇怪的设定,在PHP中可以将命名空间映射到对应的文件名然后加载对应的类,但是文件名和类名也不一定是完全相同的。
开发环境
在IDE
上纠结了半天,尝试了Eclipse
之后最终选择了的 Intellij IDEA
,主要是一直Intellij
全家桶,相关配置啥的都比较熟悉。 PS:向用编辑器写代码的大佬低头...
基础语法
数据类型
分类 Java是强类型语言,其数据类型主要分为基本数据类型和引用数据类型(这个分类跟JavaScript很像)
- 基本数据类型
- 整数类型
byte
,short
,int
,long
- 浮点数类型
float
,double
- 布尔类型
boolean
- 字符类型
char
- 整数类型
- 引用数据类型
- 对象
隐式类型转换 相比与JavaScript中的各种花式隐式数据类型转换,Java中的隐式数据类型转换(也称作自动转换)主要是指数字类型按容量从小到大的自动提升
byte,short,char --> int --> long --> float --> double
这里需要注意的是byte, short和char都是平级的,因此无法自动转换,可以使用强制类型转换。
强制类型转换 在Java中强制类型转换是非常常见的,如果你明确知道数据是可以用该数据类型来表示的,可以用强制转换,一般用在将高级变量转换为低级变量(可能造成精度丢失)。强制类型转换的父类和子类之间的转换是十分常见的,后面会着重提到。
执行流程
顺序,分支和循环
分支 分支包括if
和switch
:
if
条件表达式的结果必须强制转换为boolean
类型,否则无法通过编译。switch
中的变量类型可以是byte
、short
、int
或者char
,现在也支持字符串,对应的case
必须为字符串常量或者字面量
循环 循环包括while
,do-while
和for
,以及跳出循环的continue
和break
,使用方法跟JavaScript基本相同。 此外Java提供了一种用于数组的增强型for循环,用于遍历数组
数组
Java中的数组是用来存储固定大小的同类型元素,这跟C++相似。需要注意的是声明数组字面量采用的是{}
而不是[]
,数组索引也是从0开始的。
int [] arr = {1, 2, 3, 4, 5};
for(int x : arr ){
System.out.println( x );
}
函数
Java中没有函数,只有方法,切记切记。
其他
此外还有一些零碎的语法:
- 标识符命名大小写敏感,不能以数字开头,不能使用关键字
- 关键字与
C++
比较相似,用IDE的话也不用太在意这个问题了 - 支持多行注释
/**/
和单行注释//
- 支持
++
及--
自增增减操作符 - 支持
>>>
按位右移补零操作符 - 运算符优先级这个问题也比较相似
对象
Java是一门纯粹的面向对象的语言(这句话貌似见了很多次),除了包的声明和引用之外所有代码都只能出现在类(接口)中。
变量
类中的变量主要分为了三类:局部变量,成员变量和类变量
局部变量 指的是在方法内部声明的变量,其作用域仅存在于方法中,参数也属于局部变量。局部变量在方法执行时创建,并在方法调用结束后销毁。 局部变量在使用前必须进行初始化操作。
实例变量 实例变量即成员变量,指每个实例对象都具备的变量,同个类下多个实例对象之间的成员变量互不影响。 实例变量在创建对象的时候实例化,且可以在方法中直接调用(如果与局部变量同名则可以使用this
来显示调用成员变量) 实例变量总是会有默认值的(根据数据类型不同其默认值也不一样)
类变量 指某个类持有的变量,即声明为static
类型的静态变量。多个对象共享同一个静态变量。可以把静态变量看作是特殊的实例变量,因此它也总是有默认值的。
方法
函数签名包括参数类型,参数个数,参数顺序,编译器通过函数签名调用对应的方法(重载)。
Java中所有的赋值和方法调用的参数都是“按值“处理的,引用类型的值是对象的地址,基础类型的值是其自身(这句话貌似在《你不知道的JavaScript》中也见到过)
程序的的入口方法是public static void main(String []args){}
。
包
Java使用包对类和接口进行分类,防止命名冲突以及限制访问权限,可以理解为命名空间。
创建包 包声明应该在源文件的第一行,每个源文件只能有一个包声明,这个文件中的每个类都应用于它
package com.example.txm
引入包
// 导入类,最常用的做法
import xxx.xxx.xxxClass
// 导入整个包
import xxx.xxx.xxx.*
// 导入静态成员
import static xxx.xxx.*
需要注意的是:
- 在同一个包中,一个类想要使用本包中的另一个类,那么该包名可以省略
- Java本身就内置了一些包(比如
java.lang
等),不需要显示引入就可以直接使用的。
垃圾回收
Java中的实例对象都保存在堆上,而对象的变量名只是保持对某个对象的引用(比如堆地址?),可以改变某个变量的引用(当然得保证类型相同或兼容)。 如果堆上的某个对象没有被任何变量引用(计数器置为0),那么该对象就会被垃圾回收器回收,具体的细节目前并没有深入,JavaScript中也是采用相同的计数垃圾回收机制。
面向对象
面向对象的核心就是抽象,封装,继承和多态(多么学术的回答~),在Java中能够完美的实现。下面是《Head First Java》中关于面向对象的一些建议,这里一并整理出来:
- 找出具有共同属性和行为的对象(抽象)
- 设计代表共同状态的类,用继承来防止出现重复的代码(继承)
- 对象可以提供统一的接口供外部使用,而隐藏内部的数据和方法实现(封装)
- 决定子类是否需要让某项行为有特定的不同的运作方式(多态)
- 通过寻找使用共同行为的子类来找出更多抽象化的机会,实现类的继承层次(继承)
抽象
这是一个仁者见仁的问题,我现在就是一个菜鸡~这里先撤了...
封装
通过封装,对象只向外部暴露功能接口,而隐藏内部实现。这样能够保证每个类都有较好的独立性,便于程序维护
- 从使用者的角度看,如果需要替换某个类,只需要保证替换类提供了相同的接口,完全不需要去更改内部的实现代码
- 从维护者的角度看, 或者要优化某个类,只需要保证暴露的接口不发生更改,内部实现的修改不会影响外部的功能
继承
如何设计父类是一个问题,如何设计需要继承的子类是另外一个问题。需要明白的是:继承概念下的IS-A
是个单向的关系。
子类可以继承父类的成员,包括变量和方法;反之,父类可以通过存取权限决定子类是否能够继承某些特定成员
多态
Java中的多态简直可怕。 在多态下,变量引用和对象可以不相同,换句话说,运行多态时,引用类型可以是实际对象类型的父类,参数和返回类型也可以是多态
访问修饰符
除了常规的private
,protected
,public
之外,Java还提供了default
的访问修饰符。如果不对成员变量和方法使用任何访问修饰符,则其默认为default
。default
修饰的类型或成员只能被自己和同一个包里的(不包括子包)其他类型访问。
下面是关于访问修饰符的总结(这个表示从网上拿过来的,貌似已经找不到出处了)
类内部 | 本包 | 子类 | 外部包 | |
---|---|---|---|---|
public | ~ | ~ | ~ | ~ |
protected | ~ | ~ | ~ | |
default | ~ | ~ | ||
private | ~ |
内置对象
Java提供了大量有用的内置对象,比如日期,数学计算,正则表达式,常用的抽象数据类型等。相关的东西在使用中慢慢学习,因此又得准备一本手册(/掩面)。
Date
与日期相关的类有
Date
封装当前的日期和时间SimpleDateFormat
格式化分析日期Calendar
设置和获取日期数据的特定部分
Math
封装了随机值,取整等方法
Math.random
Math.ceil
Math.floor
Math.round
小结
简单过了一遍Java基础,很多东西都只是有了一个概念而已,在今后的学习中慢慢填坑吧。
你要请我喝一杯奶茶?
版权声明:自由转载-非商用-保持署名和原文链接。
本站文章均为本人原创,参考文章我都会在文中进行声明,也请您转载时附上署名。