Java基础
Java起源
Java programming language具有大部分编程语言所共有的一些特征,被特意设计用于互联网的分布式环境。Java具有类似于C++语言的"形式和感觉",但它要比C++语言更易于使用,而且在编程时彻底采用了一种"以对象为导向"的方式。使用Java编写的应用程序,既可以在一台单独的电脑上运行,也可以被分布在一个网络的服务器端和客户端运行。另外,Java还可以被用来编写容量很小的应用程序模块或者applet,做为网页的一部分使用。applet可使网页使用者和网页之间进行交互式操作。
Java是Sun微系统公司在1995年推出的,推出之后马上给互联网的交互式应用带来了新面貌。最常用的两种互联网浏览器软件中都包括一个Java虚拟机。几乎所有的操作系统中都增添了Java编译程序。后来 Sun 公司被 Oracle (甲骨文)公司收购,Java 也随之成为 Oracle 公司的产品。
Java分为三个体系:
- JavaSE(J2SE)(Java2 Platform Standard Edition,java平台标准版)
- JavaEE(J2EE)(Java 2 Platform,Enterprise Edition,java平台企业版)
- JavaME(J2ME)(Java 2 Platform Micro Edition,java平台微型版)。
Java的一些相关术语。
- JDK(Java Development Kit ):编写Java程序的程序员使用的软件
JDK 从某种意义上可以理解为Java SDK 。
- JRE(Java Runtime Environment):运行Java程序的用户使用的软件
- Server JRE (Java SE Runtime Environment):服务端使用的 Java 运行环境
- SDK(Software Development Kit):软件开发工具包
android SDK 安卓软件开发包 Java SDK
- DAO(Data Access Object):数据访问接口,数据访问,顾名思义就是与数据库打交道
- MVC(Model View Controller):模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用于组织代码用一种业务逻辑和数据显示分离的方法
第一个Java程序
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World"); } } //String args[] 与 String[] args 都可以执行,但推荐使用 String[] args,这样可以避免歧义和误读。
java程序的执行基础命令的解析。
依次执行以下命令
javac HelloWord.java java HelloWord
javac 后面跟着的是java文件的文件名,例如 HelloWorld.java。
该命令用于将 java 源文件编译为 class 字节码文件,如: javac HelloWorld.java。
运行javac命令后,如果成功编译没有错误的话,会出现一个 HelloWorld.class 的文件。
java 后面跟着的是java文件中的类名,例如 HelloWorld 就是类名,如: java HelloWorld。
注意:java命令后面不要加.class。
在这里提一下,参数args的作用:
参数args是Java编译器要求必须做的,用来存储命令行参数的。
注意点
- Java对大小写特别敏感。A和a不相同。
- 类名,类名首字母大写,若是由若干单词组成,每个单词的首字母大写。HelloWord
- 方法名,所有方法名以小写字母开头,如果方法名含有若干单词,则后面的每个单词首字母大写。myAction
- 源文件名,源文件名必须与类名相同,文件名必须与public的类名相同。
public class test{ public static void main(String[] args){ ...... } } 该文件名需为test.java
所有的Java程序都由 public static void main(String[] args)方法开始执行。
Java基本语法
Java标识符
简单来记,自己起了名字的都可以称为标识符,如类名,方法名,变量名。
命名规范(驼峰命名法)
- 项目的命名:项目的命名全部小写
- 包的命名:package 的名字由全部小写的字母组成,例如:com.test
- 类名和接口名:每个单词首字母大写,其余小写,例如:public class MyClass{}
- 方法名:方法的名字用一个小写字母开头,后面的单词用大写字母开头,例如:run(),getBalance()。
- 变量名:变量的名字用一个小写字母开头,后面的单词用大写字母开头,例如:index,currentImage。
- 常量名:基本数据类型的常量名使用全部大写,单词之间使用下划线分割。例如:public static final String GAME_COLOR="RED";
注意点
- 所有的标识符都应该以字母(A-Z 或者 a-z),美元符($)、或者下划线(_)开始
- 首字符之后可以是字母(A-Z 或者 a-z),美元符($)、下划线(_)或数字的任何字符组合
- 关键字不能用作标识符
- 标识符是大小写敏感的
- 合法标识符举例:age、$salary、_value、__1_value
- 非法标识符举例:123abc、-salary
- "$"尽量不要在代码中出现。(是由于在后面内部类中,编译后会出现$符号)
命名时,尽量不要使用中文及拼音命名。😆😆😆
这里列举一些常见的Java关键字。
类别 |
关键字 |
说明 |
访问控制 |
private |
私有的 |
protected |
受保护的 |
|
public |
公共的 |
|
default |
默认 |
|
类、方法和变量修饰符 |
abstract |
声明抽象 |
class |
类 |
|
extends |
扩充、继承 |
|
final |
最终值、不可改变的 |
|
implements |
实现(接口) |
|
interface |
接口 |
|
native |
本地、原生方法(非 Java 实现) |
|
new |
创建 |
|
static |
静态 |
|
strictfp |
严格浮点、精准浮点 |
|
synchronized |
线程、同步 |
|
transient |
短暂 |
|
volatile |
易失 |
|
程序控制语句 |
break |
跳出循环 |
case |
定义一个值以供 switch 选择 |
|
continue |
继续 |
|
do |
运行 |
|
else |
否则 |
|
for |
循环 |
|
if |
如果 |
|
instanceof |
实例 |
|
return |
返回 |
|
switch |
根据值选择执行 |
|
while |
循环 |
|
错误处理 |
assert |
断言表达式是否为真 |
catch |
捕捉异常 |
|
finally |
有没有异常都执行 |
|
throw |
抛出一个异常对象 |
|
throws |
声明一个异常可能被抛出 |
|
try |
捕获异常 |
|
包相关 |
import |
引入 |
package |
包 |
|
基本类型 |
boolean |
布尔型 |
byte |
字节型 |
|
char |
字符型 |
|
double |
双精度浮点 |
|
float |
单精度浮点 |
|
int |
整型 |
|
long |
长整型 |
|
short |
短整型 |
|
变量引用 |
super |
父类、超类 |
this |
本类 |
|
void |
无返回值 |
|
保留关键字 |
goto |
是关键字,但不能使用 |
const |
是关键字,但不能使用 |
|
Java 的 null 不是关键字,类似于 true 和 false,它是一个字面常量,不允许作为标识符使用。
Java修饰符
修饰符来修饰类中方法和属性。
public class ClassName { // ... } private boolean Flag; static final double weeks = 7; protected static final int BOXWIDTH = 42; public static void main(String[] args) { // 方法体 }
访问控制修饰符
default //默认,啥都不写。同一包内可见,不同包的子类不可见,未使用任何修饰符的都默认,使用对象:类,接口,变量,方法。 public //公共的,所有类可见,使用对象:类,接口,变量,方法。 protected //受保护的 对同一包内的类和所有子类(不同包子类)可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。 private //私有的 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类) public > protected > default > private
类的访问控制符只能是空或者public,方法和属性的访问控制符可以是public,private,protected,default.
访问范围 |
private |
default |
protected |
public |
同一个类 |
可以访问 |
可以访问 |
可以访问 |
可以访问 |
同一个包中的其他类 |
不可访问 |
可以访问 |
可以访问 |
可以访问 |
不同包中的子类 |
不可访问 |
不可访问 |
可以访问 |
可以访问 |
不同包中的非子类 |
不可访问 |
不可访问 |
不可访问 |
可以访问 |
private
private 修饰的类成员,只能被该类自身的方法访问和修改,而不能被任何其他类(包括该类的子类)访问和引用,具有最高的保护级别。
public class Logger { private String format; public String getFormat() { return this.format; } } format 变量为私有变量,所以其他类不能直接得到该变量的值,为了能够是其他类能够操作该变量,定义了public方法,getFormat(),来返回format 的值。
protected
用保护访问控制符 protected 修饰的类成员可以被三种类所访问:该类自身、与它在同一个包中的其他类以及在其他包中的该类的子类。
protected 可以修饰数据成员,构造方法,方法成员,不能修饰类(内部类除外)。接口及接口的成员变量和成员方法不能声明为 protected。
class AudioPlayer { protected boolean openSpeaker(Speaker sp) { // 实现细节 } } class StreamingAudioPlayer extends AudioPlayer { protected boolean openSpeaker(Speaker sp) { // 实现细节 } } 子类重写父类的方法。
public
当一个类被声明为 public 时,它就具有了被其他包中的类访问的可能性,只要包中的其他类在程序中使用 import 语句引入 public 类,就可以访问和引用这个类。、
public static void main(String[] arguments) { // ... }
default
默认访问修饰符-不使用任何关键字
使用默认访问修饰符声明的变量和方法,对同一个包内的类是可见的。接口里的变量都隐式声明为 public static final,而接口里的方法默认情况下访问权限为 public。
String version="1.5.1"; boolean s(){ return true; }
注意:
- 父类中声明为 public 的方法在子类中也必须为 public。
- 父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public,不能声明为 private。
- 父类中声明为 private 的方法,不能够被子类继承。
非访问控制修饰符
final //不可改变的,用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。 abstract //声明抽象,用于创建抽闲类和抽象方法 static //静态 用于修饰类方法和类变量 synchronized //线程,同步 transient //用来预处理类和变量的数据类型。 volatile 修饰符
final修饰符
final 最终,也可以称为完结器,表示对象的最终形态,不可改变的意思。
final修饰变量
final 修饰的变量即成为常量,只能赋值一次。
- final 修饰的局部变量必须使用之前被赋值一次才能使用。
- final 修饰的成员变量在声明时没有赋值的叫“空白 final 变量”。空白 final 变量必须在构造方法或静态代码块中初始化。、
public class FinalDemo { void doSomething() { //局部变量 // 没有在声明的同时赋值 final int e; // 只能赋值一次 e = 100; System.out.print(e); // 声明的同时赋值 final int f = 200; } // 实例常量 final int a = 5; // 直接赋值 final int b; // 空白final变量 // 静态常量 final static int c = 12;// 直接赋值 final static int d; // 空白final变量 // 静态代码块 static { // 初始化静态变量 d = 32; } // 构造方法 FinalDemo() { // 初始化实例变量 b = 3; // 第二次赋值,会发生编译错误 // b = 4; }
注意:final 修饰的变量不能被赋值这种说法是错误的,严格的说法是,final 修饰的变量不可被改变,一旦获得了初始值,该 final 变量的值就不能被重新赋值。
final 修饰基本类型变量和引用类型变量的区别
- 当使用 final 修饰基本类型变量时,不能对基本类型变量重新赋值,因此基本类型变量不能被改变。
- 但对于引用类型变量而言,它保存的仅仅是一个引用,final 只保证这个引用类型变量所引用的地址不会改变,即一直引用同一个对象,但这个对象完全可以发生改变。
import java.util.Arrays; class Person { private int age; public Person() { } // 有参数的构造器 public Person(int age) { this.age = age; } // 省略age的setter和getter方法 // age 的 setter 和 getter 方法 } public class FinalReferenceTest { public static void main(String[] args) { // final修饰数组变量,iArr是一个引用变量 final int[] iArr = { 5, 6, 12, 9 }; System.out.println(Arrays.toString(iArr)); // 对数组元素进行排序,合法 Arrays.sort(iArr); System.out.println(Arrays.toString(iArr)); // 对数组元素赋值,合法 iArr[2] = -8; System.out.println(Arrays.toString(iArr)); // 下面语句对iArr重新赋值,非法 // iArr = null; // final修饰Person变量,p是一个引用变量 final Person p = new Person(45); // 改变Person对象的age实例变量,合法 p.setAge(23); System.out.println(p.getAge()); // 下面语句对P重新赋值,非法 // p = null; } }
在使用 final 声明变量时,要求全部的字母大写,如 SEX,这点在开发中是非常重要的。
如果一个程序中的变量使用 public static final 声明,则此变量将称为全局变量,如下面的代码:
public static final String SEX= "女";
final修饰方法
在声明类中,final方法只被实现一次。
final修饰的方法不可被重写。
public class FinalMethodTest { public final void test() { } } class Sub extends FinalMethodTest { // 下面方法定义将出现编译错误,不能重写final方法 public void test() { } }
但是,final修饰的方法可以被重载。
public class FinalOverload { // final 修饰的方法只是不能被重写,完全可以被重载 public final void test(){} public final void test(String arg){} }
注意点:
对于一个 private 方法,因为它仅在当前类中可见,其子类无法访问该方法,所以子类无法重写该方法——如果子类中定义一个与父类 private 方法有相同方法名、相同形参列表、相同返回值类型的方法,也不是方法重写,只是重新定义了一个新方法。因此,即使使用 final 修饰一个 private 访问权限的方法,依然可以在其子类中定义与该方法具有相同方法名、相同形参列表、相同返回值类型的方法。
public class PrivateFinalMethodTest { private final void test() { } } class Sub extends PrivateFinalMethodTest { // 下面的方法定义不会出现问题 public void test() { } } 这样的写法相当于子类重新定义了一个新方法,并不是重写父类的方法。
final修饰类
final修饰的类不可被继承。
当某个类被final修饰时,意味着此类无后代,不需要进行修改或扩展。
final class SuperClass { } class SubClass extends SuperClass { //编译错误 }
这一知识点,可以参考以下文章,这位大佬讲的非常清晰。
http://c.biancheng.net/view/6053.html
abstract修饰符
abstract表示“抽象的”,只能用来修饰类和方法,不能修饰属性。
- 如果用来修饰类,表示该类是一个抽象类;
- 如果用来修饰方法,表示该方法是一个抽象方法。
private私有的、static静态的、final方法和final类,都不能用abstract来修饰!
abstract 修饰的类为抽象类。
抽象类可以包含抽象方法和非抽象方法。
如果一个类包含抽象方法,那么该类一定要声明为抽象类.
abstract class 类名 { public int a; public abstract void goFast(); //抽象方法 public abstract void changeColor(); }
抽象方法
- 抽象方法是一种没有任何实现的方法,该方法的具体实现由子类提供。
- 抽象方法不能被声明成 final 和 static。
- 任何继承抽象类的子类必须实现父类的所有抽象方法,除非该子类也是抽象类。
- 如果一个类包含若干个抽象方法,那么该类必须声明为抽象类。抽象类可以不包含抽象方法。
public abstract class SuperClass{ abstract void m(); //抽象方法 } class SubClass extends SuperClass{ //实现抽象方法 void m(){ ......... } }
synchronized 修饰符
synchronized 关键字声明的方法同一时间只能被一个线程访问。synchronized 修饰符可以应用于四个访问修饰符。
public synchronized void showDetails(){ ....... }
transient 修饰符
序列化的对象包含被 transient 修饰的实例变量时,java 虚拟机(JVM)跳过该特定的变量。
该修饰符包含在定义变量的语句中,用来预处理类和变量的数据类型。
public transient int limit = 55; // 不会持久化 public int b; // 持久化
volatile 修饰符
volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。
一个 volatile 对象引用可能是 null。
public class MyRunnable implements Runnable { private volatile boolean active; public void run() { active = true; while (active) // 第一行 { // 代码 } } public void stop() { active = false; // 第二行 } } 通常情况下,在一个线程调用 run() 方法(在 Runnable 开启的线程),在另一个线程调用 stop() 方法。 如果 第一行 中缓冲区的 active 值被使用,那么在 第二行 的 active 值为 false 时循环不会停止。 但是以上代码中我们使用了 volatile 修饰 active,所以该循环会停止。
Java程序三级跳
* int a 这是一个表达式,int a; 这是一个语句
语句可以包含多个表达式
* int a =1;这是一个语句,包含两个语句。
敲黑板
int x=1; int y=3.0; System.out.println(x/y); 如果除数和被除数都是整数(分母不为0),那么就仅取计算结果的整数部分, 注意,不是4舍5入,而是直接舍弃,如29/10=2,而不是2.9,也不是3 如果要计算1/3,得到浮点数,一般采取1.0/3或1/3.0
Java变量
变量就是指代在内存中开辟的存储空间,用于存放运算过程中需要用到的数据。
变量的声明
变量必须先声明后使用,相同的变量只能声明一次。
变量类型 变量名=变量值 int x=1; int x=10,y=10;
未经声明的变量不能使用,直接使用会有编译错误。
同时声明变量后,该变量只能存储制定好的数据类型的的数据,否则会产生编译错误。
变量的命名
命名规则:
- 满足标识符的命名规则;
- 符合驼峰法命名规范;
- 尽量简单,做到见名知意;
变量的类型
成员变量
- 成员变量定义在类中,在整个类中都可以被访问。
- 成员变量随着对象的建立而建立,随着对象的消失而消失,存在于对象所在的堆内存中。
- 成员变量有默认初始化值。
局部变量
- 局部变量只定义在局部范围内,如:函数内,语句内等,只在所属的区域有效。
- 局部变量存在于栈内存中,作用的范围结束,变量空间会自动释放。
- 局部变量没有默认初始化值
静态变量
- 静态变量随着类的加载而存在,随着类的消失而消失。
- 静态变量可以被对象调用,还可以被类名调用。
- 静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据。
在使用变量时需要遵循的原则为:就近原则
首先在局部范围找,有就使用;接着在成员位置找。
class Test{ private String name;//成员变量,实例变量 private int age; static String country="CN";//静态变量 public Test(){}; //name,age 为成员变量 public Test(String name,int age){ this.name=name; this.age=age; } public void start(){ String tests="hello"; //局部变量 System.out.println("姓名:"+name +" 年龄:"+age); } //i为局部变量 for(int i=0;i<36;i++){ ...... } } public class StaticDemo{ public static void main(String[]args){ Test test = new Test(); System. out.println(test.country); //可以用类名直接调用 System. out.println(Test.country); } }
成员变量 |
局部变量 |
静态变量 |
|
定义位置 |
在类中,方法外 |
方法中,或者方法的形式参数 |
在类中,方法外 |
初始化值 |
有默认初始化值 |
无,先定义,赋值后才能使用 |
有默认初始化值 |
调用方式 |
对象调用 |
--- |
对象调用,类名调用 |
存储位置 |
堆中 |
栈中 |
方法区 |
生命周期 |
与对象共存亡 |
与方法共存亡 |
与类共存亡 |
别名 |
实例变量 |
--- |
类变量 |