JAVA基础知识
Java 是SUN(Stanford University Network,斯坦福大学网络公司)1995年推出的一门面向 Internet 的高级编程语言。
Java 虚拟机(JVM:Java Virtual Machine)
JRE(Java Runtime Environment):Java 运行环境
(包括 JVM 和 Java 程序所需的核心类库等,给用户使用的)
JDK(Java Development Kit)Java开发工具包(包括JRE,给Java开发人员使用的)使用 set 设置临时环境变量
java set Path=xxx
在写简单的 HelloWorld 程序的时候,可以使得 java 文件名与类名不一致,最后得到的字节码文件的文件名是和类名相同的;当包含 main 函数的类有 public 的时候,必须使得java文件名和类名一致,规定的。
注意区别 set classpath=c: 与 set classpath=c:; 的区别(分号的有无),不加分号只在当前目录找,加了分号先到当前目录找。所以以后不要加分号为好。
注意 path 和 classpath 查找先后的区别:
path是先到当前目录查找,没找到,再到path环境查找;
classpath 是先到 classpath 环境查找,没找到,再到当前目录查找(前提加了分号)文档说明书:对于文档注释,是java特有的注释,其中注释内容可以被JDK提供的工具 javadoc.exe 所解析,生成一套以网页文件形式体现的该程序的说明文档
配置 JAVA 开发环境
JAVA_HOME = D:\jdk1.8.0_144
PATH = .;%PATH%;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;
CLASSPATH = .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar
JAVA 环境安装验证
java -version
javac -version
第一个 JAVA 程序
public class Demo
{
public static void main(String[] args)
{
System.out.println("Hello Java!");
}
}
标识符
标识符的组成:数字,字母,下划线,美元符号
开头不能使用数字。
可以使用中文作为变量名(编辑代码的文本要为GBK格式,才能支持中文作为变量名)
JAVA中的名称规范
包名:多单词组成时所有字母都小写(xxxyyyzzz)
类名接口名:多单词组成时,所有的单词的首字母大写(XxxYyyZzz)
变量名和函数名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写(xxxYyyZzz)
常量名:所有字母都大写,多单词时每个单词用下划线连接(XXX_YYY_ZZZ)
常量与变量
常量
- JAVA中可以通过 final 关键字定义常量。例如:final int i = 0;
数据类型
数据类型 = 基本数据类型 + 引用数据类型
基本数据类型 = 整数型(byte,short,int,long) + 浮点型(float,double) + 字符型(char) + 布尔型(boolean)
引用数据类型 = 类(class) + 接口(interface) + 数组([])
1、整数型
byte(-128 ~ 127)
short(-32768 ~ 32767)
int(-2147483648 ~ 2147483647)
Tips:
- JAVA 中没有无符号整数型变量
- 隐式类型转换(byte,short,char->int->long->float->double)
- byte,short,char之间不会相互转换,它们三者之间在计算时首先转换成int类型,然后进行计算。
- 容量大的数据类型转换成容量小的数据类型时,要加强制转换符,但是会造成精度降低或者溢出。
- 有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那一种,然后再进行计算。
2、浮点型
- JAVA 中 float 型浮点数加上后缀 f 或 F。
- JAVA 中 double 型浮点数加上后缀 d 或 D。
- JAVA 浮点数的默认类型是 double。
- 将一个 float 类型的数,强制转换成 long 类型,会舍去小数部分,而不是四舍五入。
3、逻辑型和字符型
- JAVA中的逻辑型又叫布尔型,是一种只能表示 true 和 false 两种值的类型。
- JAVA中的字符型占用两个字节,能够表示 Unicode 字符(比如汉字)。
char c1 = ‘c‘;
char c2 = ‘冯‘;
4、引用数据类型
- JAVA 中的引用数据类型类似 C 语言中的指针类型;
- JAVA 中的引用数据类型主要用于类 class 定义的复杂数据类型(不是基本的数据类型,在代码里面是不会高亮显示的,如String类型,是class定义的复杂数据类型。)
- JAVA 中引用数据类型变量和常量的定义方式与基本数据类型相同。
- 引用数据类型包括:类class,接口interface,数组。
运算符
1、算术运算符
- ++和-- 优先级最高
- 乘,/,% 优先级其次
- +和- 优先级最低
- 括号可以改变优先级
Tips:
1、如果对负数取模,可以把模数的负号忽略,如 5%-2=1,但是被模数是负数就另当别论。
2、对于除号"/",它的整数除和小数除是由区别的:整数之间做除法时,只保留整数部分而舍弃小数部分;小数之间做除法时(不论除数是小数还是被除数是小数)结果都是浮点类型。
3、"+"号除了字符串相加功能之外,还能把非字符串转化为字符串。(System.out.println("5+5="+5+5); "+"运算符两侧的操作数只要有一个是字符串String类型,系统会自动将另一个操作数转换成字符串然后在进行连接。)
2、逻辑运算符
- ! 运算优先级最高
- && 运算优先级其次
- || 运算优先级最低
- 括号可以改变优先级
3、关系运算符
- JAVA 中同类型的变量和常量都可以使用 == 和 != 来判断是否相等;
- JAVA 中关系运算符的结果是个布尔值,而不是C语言中的1或0;
- 关系运算符常和逻辑运算符一起使用。
4、位运算符
- 位运算符是对整数进行二进制操作的运算符,返回的结果也是一个整数;
- 位运算符有按位取反~,按位与&,按位或|和按位异或^;
- 移位运算符是左移<<,右移>>,无符号右移>>>.
5、条件运算符
- Java中的条件运算符根据条件来返回一个值
- x = (布尔表达式) ? (为true时所赋的值) : (为false时所赋的值);
- 例如:String s = (num < 2500)?("房贷没压力"):("房贷太高了");
1、if-else-
- 略
2、switch-case-
- switch语句中的条件表达式只能是int,short,byte,char
- switch语句中的case后必须是常量且不能重复。
成员变量
成员变量(类的属性)和局部变量的区别:
成员变量:如果没有初始化和赋值的话,默认初始值为 0
局部变量:没有初始化的时候,访问的时候会报错
引用
- JAVA 语言中除了基本类型之外的变量类型都称之为引用类型,如String类型。
当使用String s; 的时候,实际上有两片内存,一片是一个索引叫s(栈),里面装的是一个地址;当 s = new String("JAVA"); 的时候,s才指向另一片空间(堆),这篇空间的内容为 "JAVA"。所以s并不是"JAVA",而是"JAVA"的引用。
一提到引用的概念,立马想到一小块内存(栈)指向一大块内存(堆)。
构造方法
- 使用new + 构造方法 创建一个新对象
- 当没有指定构造函数时,编译器为类自动添加默认构造函数。
- 构造方法是在 JAVA 类中的一个用来初始化对象的函数
- 构造方法与类同名且没有返回值
第三章内存解析6-11课实在是太精彩了,不多说,自己看!!!
方法重载(Overload)
- 方法名相同 + 参数不同:参数个数不同/参数类型不同
- 返回值类型不同(不构成重载)
与普通方法一样,构造方法也可以重载
不同类型的内存分布
当创建该类对象的时候,静态变量、静态方法就会被放到内存里了,就算没有new一个对象,static静态变量依然存在于 data segment 区域。
内存分为四个区:stack segment,heap segment,data segment,code segment;
stack 区存放函数参数和局部变量;
heap 区存放对象(包括成员变量:成员变量在堆内存分配,因为成员变量只有在new出来的时候才会分配空间,所以分配在堆内存;而局部变量分配在栈内存。);
data 区存放static 的变量或者字符串常量;
code 区存放类中的方法;
this 指针
- 在类的方法定义中使用的this关键字代表使用该方法的对象的引用。
- 哪个对象调用该方法的this,this就指向哪个对象。
- this可以看成一个成员变量,它的值是当前对象的引用。
static关键字
- 在类中,用static声明的成员变量为静态成员变量,它为该类的功用变量,在第一次使用(第一次new一个对象的时候)的时候被初始化,对于该类的所有对象来说,static成员变量只有一份。
- 用static声明的方法为静态方法,在调用该方法的时候,不会将对象的引用传递给它,所以在static方法中不可以方位非static的成员。
- static成员变量分配在数据区,所以内存的布局,除了 stack 和 heap 之外又多了一块 Data Segment 区域。
静态成员变量可以使用 “类名.静态成员变量” 来访问,当然也可以使用 “对象.静态成员变量” 来访问。
静态成员函数不能调用非静态成员成员变量和非静态成员函数,因为静态的成员函数不需要new一个对象出来(使用static声明的方法为静态方法,在调用该方法的时候,不会将对象的引用传递给它,所以在static方法中不可访问非static成员),既然没有对象,那么其内的非静态成员变量和非静态成员函数就无法执行,所以静态成员函数不能调用非静态成员成员变量和非静态成员函数。
静态与非静态的成员变量都可以在定义的时候赋值,只不过意义不同。
package 和 import
为了便于管理大型软件系统中数目众多的类,解决类的命名冲突的问题,java引入包(package)机制,提供类的多重类命名空间。相当于对相同名字的不同类加上了一个独一无二的路径。
package 语句作为 java 源文件的第一条语句,指明该文件中定义的类所在的包。(若缺省包语句,则为无名包)
给包取名,约定俗成的是公司的域名倒过来:例如公司为www.google.com,那么给你的类打包时取名可以是:package com.google.javatest;等。
java编译器把包对应于文件系统的目录管理,package语句中,用"."来指明包目录的层次,如上package com.google.javatest,表示该文件中所在的类位于 "./com/google/javatest"目录下。如果其他的类调用了该文件中的类,那么该文件的类对应的class文件就需要位于"./com/google/javatest" 目录下。
假如该文件中的一个类叫Cat类,那么在其他类使用的时候,比如new一个Cat对象,那么就要这么写:
java com.google.javatest.Cat cat = new com.google.javatest.Cat();
**需要把Cat类的路径加上,否则找不到这个Cat类(如果将一个类打包,则使用该类时,必须使用该类的全名,java编译器才能找到该类)。这样就太麻烦了,解决办法就是使用import。使用import在文件的开头引入要使用的类,例如 import com.google.javatest.Cat;import com.google.javatest.*;**
可以不需要使用 import 语句直接使用java.lang包中的类,比如String类。
注意打包的源文件可能对编译产生影响,可以将打完包(生成了对应的class文件)的源文件(java源文件)删除或者转移目录。
注意:如果按照以上import com.google.javatest.Cat;的写法,那么我们调用Cat类的 java 源文件的路径要和com路径位于同一层目录,否则又会找不到路径。(必须class文件的最上层的包的父目录位于classpath下。比如上面的class文件最上层的包是com目录,com目录的父目录是当前目录,就是"."目录,是位于classpath目录下的。)
java提供的包
怎么看java提供的包有哪些呢?位于D:\Java\jdk\jre\lib\rt.jar里面,解压出就可以看到。
主要包介绍:
- java.lang 包含一些java语言的核心类,如String,Math,Integer,System和Thread,提供常用功能。
- java.awt 包含了构成抽象窗口工具集的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。
- java.applet 包含applet运行所需的一些类。
- java.net 包含执行与网络相关的操作的类。
- java.io 包含能提供多种输入输出功能的类。
- Java.util 包含一些实用工具类,如sing一系统特性,实用与日期日历相关的函数。
PS:可以不需要使用import语句直接使用java.lang包。
怎么打包我们自己的包为jar文件呢?执行:jar -cvf xxx.jar path(path表示你需要打包的包的路径)
可以把jar包文件当成路径设置到classpath变量,这样我们就可以使用jar包。效果和真实的路径相同。
继承和权限控制
修饰符 | 类内部 | 同一个包 | 子类(可以不同的包) | 不同包的非子类 |
---|---|---|---|---|
private | yes | |||
default | yes | yes | ||
protected | yes | yes | yes | |
public | yes | yes | yes | yes |
- 类的可见性
- java 语言规定一个文件只能有一个类被声明为 public
- public的类必须与文件名完全相同。
- public类可以被其他包中的类导入使用,default类只能被同一个包内部的类访问
- protected 和 private 不能用于限定类的可见性,对类的修饰权限只能使用public和default
- 类的继承
- java中使用 extends 关键字实现类的继承机制。
- java只支持单继承,不允许多继承。
- 一些建议
- 每个属性和方法都显式声明访问权限,不使用默认权限。
- 对于逻辑上对外不可见的属性和方法尽量设置为private。
- 虽然java语言中同一个包中的其他非子类可以自由访问protected成员,但这是不推荐的。
- 将逻辑上相关的类组织在一个包中,以包的形式组织程序的类。
方法重写(override/overwrite)
在子类中可以根据需要对从基类中继承来的方法进行重写。
重写方法必须与被重写方法具有相同的方法名称,参数列表,返回值。(就是方法一模一样才行)
重写方法不能使用比被重写方法更严格的访问权限。
super关键字
在java中使用 super 来引用基类的成员。
当子类和父类有同名成员变量的时候,子类成员变量不会覆盖父类成员变量,子类成员变量重写父类的成员变量,使得父类成员变量被隐藏,使用super 可以访问父类成员变量。
-当一个子类继承父类时,相当于子类自动多了两个成员变量,一个是this,指向子类对象,一个是super指向子类对象中的父类对象。
继承中的构造方法
子类的构造过程中必须调用其基类的构造方法(先父母,后客人,最后自己)
子类可以在自己的构造方法中使用 super 调用基类的构造方法(使用 this调用本类的另外构造方法)
如果子类的构造方法没有显式调用基类的构造方法,则系统默认调用基类的无参数的构造方法。
如果子类构造方法中既没有显式调用基类构造方法,而基类中又没有无参数的构造方法,则编译出错。
Object 类之 toString 方法
Object类是所有 java 类的根基类。
如果在类的声明中未使用 extends 关键字指明其基类,则默认基类为Object 类。
Object 类的 toString 方法,建议所有子类覆盖此方法(It is recommended that all subclasses override this method.)
Object类之 equals 方法
Object 类中定义 public boolean equals(Object obj) 方法,提供对象是否相等的逻辑。
Object 的 equals 方法定义为:x.equals(y)当x和y是同一个对象的引用时返回 true,否则返回 false。
java SDK 提供的一些类,如String,Date等,重写了Object的 equals 方法,调用这些类的 equals 方法,x.equals(y)当x 和y 所引用的对象是同一类对象且属性相同时(并不一定是相同对象),返回 true,否则返回false。
可以根据需要重写equals方法。
对象转型
一个基类的引用类型变量可以指向其子类的对象。
一个基类的引用不可以访问其子类对象新增加的成员(属性和方法)。
可以使用(引用变量 instanceof 类名)来判断该引用型变量所指向的对象是否属于该类或该类的子类。
子类的对象可以当做基类的对象来使用称作向上转型,反之成为向下转型。
多态/动态绑定/迟绑定
动态绑定是指在执行期间(而非编译期间)判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。
条件:
- 要有继承
- 子类重写父类方法
- 父类引用指向子类对象
- 当父类引用指向子类对象的时候,父类对象不能访问子类新增的成员变量和成员方法。
抽象类
用 abstract 关键字来修饰一个类时,这个类叫做抽象类;用 abstract 来修饰一个方法时,该方法叫做抽象方法。
含有抽象方法的类必须被声明为抽象类,抽象类必须被继承,抽象方法必须被重写。
抽象类不能被实例化。
抽象方法只需声明,而不需要实现。
final 关键字
final 的变量(成员变量,局部变量)的值不能被改变。
final 的方法不能被重写。
final 的类不能被继承。
interface 接口
接口是抽象方法和常量值的定义的集合。
从本质上讲,接口是一种特殊的抽象类,这种抽象类只包含常量(static final类型的成员变量)和方法的定义,而没有变量和方法的实现。
接口实现方式:
interface Singer {
public void sing();
public void sleep();
}
class Student implements Singer { // 学生不是继承(extends)Singer,而是实现(implements)Singer
}
- 多个无关的类可以实现(implements 类似继承)同一个接口。
interface Singer {
public void sing();
public void sleep();
}
class Student implements Singer {
// ...
}
class Dog implements Singer {
// ...
}
- 一个类可以实现(implements 类似继承)多个无关的接口。
class Teacher implements Singer, Painter {
}
- 与继承关系类似,接口与实现类之间存在多态性。
接口特性
接口可以多重实现。
接口中的成员变量默认为 public static final 的;也只能是 public static final 的。
接口中只能定义抽象方法,而且这些成员方法默认为public的,也只能是public的。
接口可以继承其他的接口,并添加新的属性和抽象方法。
如果两个接口有相同的方法,但是有个类同时实现了这两个接口会怎样呢?
- 只需要实现一次就好了。*
如果两个接口有名称相同的方法,只是返回值不一样,但是有个类同时实现了这两个接口会怎样呢?
你说同时实现这两个方法就好了,但是这两个方法并不构成重载,无法区分这两个方法的,所以目前无解,记住不要这样实现。哈哈,以后查到了再说。*
- 子类重写父类的方法时,方法的访问权限必须等于或大于父类的方法访问权限,也就是说实现接口的方法的权限必须为public,因为接口的方法为public。
否则编译的错误为:
```java Test.java:44: 错误: Worker中的playWithPet()无法实现PetCarer中的playWithPet()
void playWithPet() {
^
正在尝试分配更低的访问权限; 以前为public *
```