1. 纲要
学习语言都要了解的:
- 基本数据类型
- 高级数据类型
- 数组
- 字符串(以及相关API)
- 流程控制(循环、条件)
- 类和对象
- 核心技术
- 接口、抽象类
- 封装、继承和多态
- 异常处理
- 集合类(list、map、set)
- IO输入输出流
编写程序之前都要做的:
- 搭建环境
- Runoob熟悉基本语法
- 学习基础知识、核心技术
2. 搭建环境
- 安装 Java Development Kit
- 下载相应的安装文件,进行安装
- 环境变量的配置
- 进入此电脑-高级系统设置-高级-环境变量
- 在用户变量中的path中添加
%JAVA_HOME%\bin
- 在环境变量中新建名为
JAVA_HOME
的变量,值为安装路径,如D:\Program Files\Java\jdk-12.0.2\
- 安装 Eclipse
设置 defult location 来存放 java project - IDEA 使用方法
Project —> Module —> Package —> Class Files
3. 基础知识
3.1 背景知识
- 版本
java se 标准版,开发电脑软件(有更好的语言进行桌面开发)
java ee 企业版,开发网站(现在存活的)
java me 微机版,开发手机软件(逐渐淘汰) - 计算机相关基础知识
- 每个 0 or 1 占一 bit 位
- 8 bits = 1 Byte, 字节是数据存储的最小单位
- 宽带速率单位 Mbps 的 b 是 bit,而下载速度 MB/s 中的B是Byte
- B, KB, MB, GB, TB, PB, EB, ZB 之间各差1024倍
- 开发 java程序常用 命令提示符
- 直接写盘符名称
d:
,切换盘符根路径 cd 子文件夹名
,进入子文件夹cd ..
,返回上一级文件夹cd \
,返回盘符根路径- 按tab键,自动补全文件夹名或切换文件夹名
dir
, 查看当前文件夹下的所有文件、文件夹名cls
,清屏exit
, 关闭命令提示符界面
向系统变量添加了PATH之后, 系统会自动在系统变量中寻找程序, 所以只需要写java
就可以执行java.exe
程序.
- 直接写盘符名称
- 运行 java 程序
- JVM java virtual machine: 保证java程序能够跨平台运行
- JDK (编译器等开发工具 + JRE(运行库 + JVM))
各个平台上不同的 .java 文件经过编译器编译为 .class 文件后,不同平台上 JVM 将字节码文件解释执行,能够保证跨平台性 - 开发过程
- 源程序 .java (文件名必须与类名一样)
javac.exe
编译 .class (字节码文件)java.exe
运行 .class 文件,而不是 .java 文件
- 注释
//
单行注释/* */
多行注释 - 代码组成
public class ClassName{}
类是 java 程序的基本单位, ClassName 要和 文件名完全相同public static void main(String[] args){}
程序运行的起点- 每一行程序的结尾要有
;
- 标识符:类名、方法名、变量名
a-zA-Z
, ‘0-9’,$
, ‘_’- 不能以数字开头
- 不能是保留的关键字
3.2 基础内容
- 常量
- 字符串:双引号包围的一系列字符(可以包含多个字符)
- 整数
- 浮点数
- 字符:单引号包围的单个字符(可以是中文字符, 不能有0个或多个字符)
- 布尔常量: ture, false
- 空常量:null(不能用
System.out.println()
打印; 每次只能打印一个变量)
- 数据类型
- 基本
- 整型:byte short int long (
100
默认为int,100L
为long) - 浮点:float double(
0.2
默认为double,0.2F
为float) - 字符型: char
- 布尔型: boolean
- 整型:byte short int long (
- 引用
- 字符串
- 数组
- 类
- 接口
- Lambda
- 基本
- 变量赋值
- 为变量赋的值,不能超过其本身的取值范围(尤其是 byte和short类型)
- 用于赋值的常量的数据应该与数据类型对应 (long 类型的变量赋值时必须跟 L,float 赋值跟F)
- 用变量a为变量b赋值之后,改变a变量,b不变(赋值操作创建了新变量)
- 变量名不能重复
- 变量未赋值不可使用
- 变量使用不能超过作用域(大括号)
- 类型转换
- 占字节少的常量赋给占字节多的变量,可自动转换:byte —> short —> int —> long; float —> double
- 占字节多的常量赋给占字节少的变量,用强制转换:
int var = (int) 100L
,float var = (float) 3.14
- 避免溢出、精度损失
- 不管是字符还是数字,计算机保存的都是数字。(用ASCII码表和Unicode码表来进行编码)
- 数据与String进行计算都要转化成String(是字面转换为String,而不是数值对应的char),然后进行字符串连接操作
System.out.print("字符串加数据" + 2020)
会打印出字符串加数据2020
,不会报错 - 如果右侧数据超过左侧数据类型的范围,javac编译器会帮忙隐式地进行类型转换
表达式
- 不同类型的变量进行运算后的类型,是数据类型范围大的那个
byte, short, char都会被映射成 int进行运算
public class Demo {
public static void main(String[] args) {
short a = 5;
short b = 8;
short c = a + b; // 会报错
// short + short --> int + int --> int
short d = 5 + 8; // 不会报错
// 等号右侧都是常量,5+8 = 13,javac编译时强制进行将13转化为short
}
}
Python中
'a' + 'b'
为'ab'
,与java的引用类型字符串相同,+
是字符串连接。而java中的 char 类型是要转化为 int 来计算
布尔运算符 | 运算 | Python | Java | | —- | —- | —- | | 逻辑与 | and | && | | 逻辑或 | or | || | | 逻辑非 | not | ! |
位运算符(两种语言相同) | 运算 | Python | Java | | —- | —- | —- | | 按位与 | & | & | | 按位或 | | | | | | 按位异或 | ^ | ^ | | 按位取反 | ~ | ~ | | 左移 | << | << | | 右移 | >> | >> |
三元运算符
Java:
Python:/*
三元运算符
数据类型 变量名 = 逻辑运算 ? 变量名1 : 变量名2
*/
public class TernaryOperator {
public static void main(String[] args) {
int a = 1
int b = 2
int c = a > b ? a : b // 为c赋a, b中较大者
}
}
a, b = 1, 2
c = a if a > b else b
自定义方法
定义
方法三要素:返回值类型,方法名,参数列表
调用public static void methodName() {
System.Out.println("Hello!")
}
public static 返回值类型 方法名(参数类型 参数名, ...) {
方法体;
return 参数值;
}
public class Method{
public static void main(String[] args){
methodName();
}
public static void methodName() {
System.out.println("Hello!");
}
}
- 方法不能嵌套
- 定义之后需要调用
- 方法定义的先后顺序无所谓
- java没有函数,只有方法(有无参数,有无返回值)
- 调用:单独调用,打印调用,赋值调用
- return 后面的返回值的数据类型要与方法名前返回值类型对应
- void 类型的方法,直接写
return;
或者直接省略 - 方法重载(overload):方法的名字相同,参数列表不同(参数个数、类型、多类型顺序不同不同),与参数的名称无关
流程:顺序判断循环
IF-ELSE IF-ELSE
SWITCHpublic class Demo {
public static void main(String[] args) {
System.out.println('Hello!');
int age = 16;
if(age >= 18 && age < 60) {
System.out.println("enter the net bar.");
} else if (age >= 60) {
System.out.println("too old to play.");
} else if (age < 18 && age >= 12) {
System.out.println("it's your choice.");
} else if (age < 12 && age >= 6) {
System.out.println("you can try.");
} else {
System.out.println("really?");
}
}
}
switch(num) {
case 1:
System.out.println('1')
break;
case 2:
System.out.println('2')
break;
case 3:
System.out.println('3')
break;
default:
// break;
}
- switch后面中的小括号当中只能是:基本(byte,short,char,int),引用(String,enum枚举)
- 匹配到哪个case就从哪一个位置向下执行,可以进入其他case,直到遇到break,或者switch语句整体结束
LOOP
/*
循环结构的组成部分
1. 初始化语句
2. 条件判断语句
3. 步进语句
4. 循环体
*/
for (int i == 1; i <= 10; i++) { // 适合循环次数明确
System.out.println(i);
}
int count = 1
while (count <= 100) { // 适合循环次数不明确
System.out.println(count);
count++;
}
int count = 1
do { // 无条件执行一次,再判断条件
System.out.println(count);
count++;
} while (count <= 100);
- for循环的变量定义在小括号中,循环内部可以使用;while,do-while本身定义在外面,出循环之后仍可使用
- 循环次数明确用for循环,不明确用while
- 死循环后面有内容无法执行后面的内容,并且会报错
- do-while 的例子是,首先输入一个password,在输入正确之前重复申请输入内容
DO-WHILE
import java.util.Scanner; # 加载类的时候也应该带上标识符 ";"
public class do_while {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
int password = 1024;
int num;
do{
System.out.println("please input your password:");
num = reader.nextInt();
} while(num != password);
System.out.println("you're correct!");
reader.close();
}
}
- 关键字(与python相同)
- continue 关键字 可以跳过该层循环的剩余内容,进入下次循环
- break 关键字 可以打破循环,结束switch语句
- IDEA项目
工程层级:project — module — package — code
所有文件要写在src文件中;package的文件名用句号.
隔开的话,会创建多层级文件夹
输入psvm
会自动弹出public static void main(String[] args) {}
输入sout
会自动弹出System.out.println("*")
换行,System.out.print("*")
不换行 - 面向对象 v.s. 面向过程
- Procedure Oriented Programing, POP: 实现功能时,每个细节详细处理
- Object Oriented Programing, OOP:
- 抽象理解实际功能,将具体的事物抽象为类的对象,事物的属性抽象为属性,重复的具体操作抽象为方法;
- 可以实现封装、继承、多态;
- 具有可重用性
- 类
- 方法 method / member function
- without static;成员方法不能有static修饰,使用了static方法就不是成员方法了
- class constructor 不应该有static、void关键字
属性 attribute / member variable
- declare member variable beyond methods and within a class
- 定义在方法之外、类下的变量是成员变量,也叫全局变量;成员变量分为
- 静态成员变量 / 类变量 (static variable)
- 实例成员变量(instance variable)
- 定义在方法之内的变量是局部变量;没有静态(局部)变量,只有静态成员变量;一旦成员变量加上了static,表明该属性不再属于对象,而是类的固有特性
- 成员变量如果没有赋值,则使用默认值 (boolean:false; byte:0; short:0; int:0; long:0; char:’\u0000’; float:0.0; double:0.0; String:null; String[]:null); 然而局部变量没有默认值
- 在成员函数中,如果成员变量与传来的参数的成员变量相同,则会在成员变量的前面加上this关键字来指代该类的对象(在自动生成constructor、getter、setter的时候会有此自动操作);如果没有变量名冲突,直接使用变量名而不加this
三种变量对比 | 特点 | 类变量 | 实例变量 | 局部变量 | | —- | —- | —- | —- | | 定义位置 | 定义在类中方法外,有static修饰 | 定义在类中方法外,无static修饰 | 定义在方法中 | | 初始值 | 有 | 有 | 无 | | 调用方式 | 类名、对象均可调用类变量 | 仅可由对象调用 | 仅能在作用范围内有效 | | 生命周期 | 随着类的加载而存在 | 随着对象的创建而诞生,对着对象被垃圾回收而消失 | 随着方法入栈诞生,随着方法出栈消失 | | 存储位置 | Method Area方法区 | heap 堆内存 | stack 栈内存 |
补充虚拟机的结构体系
堆
- new出来的对象(实例变量的数据和地址);引用数据类型的数据;成员方法的地址
堆中的数据有默认值 | 类型 | 默认值 | | —- | —- | | 整型 | 0 | | 浮点型 | 0.0 | | 字符 | ‘\u0000’ | | 布尔 | false | | 引用类型 | null |
被所有线程共享
- 栈 (Stack)
- 存放局部变量
- 基本类型数据的地址和数据;自定义对象、引用数据类型的地址(地址在java中也叫引用)
- 一旦超出作用域立刻从栈内存中消失
- 三个部分:基本数据类型的变量区、执行环境上下文、操作指令区(存放操作指令)。
- 方法区 (Method Area)
- 类信息、静态成员变量、静态方法、成员方法、常量
- 被所有线程共享
- 程序计数寄存器(Program Counter Register)
保存下一条被执行指令的地址,可以是本地指针,也可以是较于该方法起指令的偏移量 - 本地方法栈 (Native Method Stack)
- JVM中变量的操作流程
- 先在方法区中为类、成员变量、成员方法(包括本类和父类的)分配内存
- 执行方法的时候入栈,为局部变量分配内存;记录引用变量的地址;保存类的对象的地址(指向堆中的对象数据)
- 在new 对象的时候,在堆中为类对象的变量、成员方法的地址(指向工作区中的成员方法)分配空间;如果有继承关系的话,由于子类对象中包含一个完整的父类对象,也会被压入堆中
在栈中的函数中,为类的对象进行赋值,相当于传递地址值,使得new出来的对象指向堆中已存在的对象数据——即两个对象引用指向同一个对象空间
- Java参数传递都是值传递
向method中传参的时候,如果给的是基本数据类型创建了新的数据,修改该数值出栈后不会影响外部的数据;但是如果传入引用数据类型、类的对象时,传参只是传入了栈中的地址,修改数据会修改参数地址指向的数据。
- Java参数传递都是值传递
基本类型变量:拷贝数值
- 引用类型变量、类的对象:拷贝引用变量、对象的引用(地址值)
- 面向对象的三大特征
- 封装(整合程序细节)
- public member variable可以通过对象访问,但private member variable只能通过全参构造方法,getter,setter间接访问
- 设置成员变量,写方法:
public void setAttriName() {}
,向其中传参;向成员变量赋值的时候,不用写**this.AttriName = ...**
,直接写**AttriName = ...**
;不能有返回值,参数类型与成员变量对应 - 获取成员变量,写方法:
public int getAttriName() {}
或者public boolean isAttriName() {}
,不能传参,返回值类型与成员变量对应(规则很清晰,所以有可能自动化生成) - new 对象的时候传入参数,为private variable赋值
- 设置成员变量,写方法:
- 通过某对象调用的成员变量/成员方法,
this
就是该对象的地址- static method 是静态成员方法,是加载类的时候放入方法区的。那个时候还没有对象,所以static method中不能出现
this.
- this 是对象引用,只能出现在非静态成员方法中
- static method 是静态成员方法,是加载类的时候放入方法区的。那个时候还没有对象,所以static method中不能出现
- 构造方法 constructor
- 用
ClassName classname = new ClassName()
新建对象的时候调用了类的构造方法 - 不能有 void 关键字,也不能有返回值
- 不写构造方法的话,编译器自动添加一个
public ClassName() {}
,没有参数,没有返回值 - 构造方法可以重载(一个无参构造方法,一个有参构造方法)
- 用
- Java的标准类的组成部分
- 所有的成员变量均用private修饰;对个成员变量对应一对getter-setter;一个无参构造方法;一个全参构造方法;
- 写完了成员变量之后,用IDE中的code - generate - getter / setter / constructor 快捷生成其他内容
- public member variable可以通过对象访问,但private member variable只能通过全参构造方法,getter,setter间接访问
继承(抽取共性)
对于已经投入使用的类,修改、增加新特性时,不要修改原类,而是定义一个新类重复利用共性内容,改动添加新内容。
extends / implements- child class继承base class中非private的成员方法、成员变量
- 访问优先级
- 不写
this
和super
:首先考虑本类的成员方法和成员变量,找不到再在父类中找- 在子类中找得到就是子类的成员方法和成员变量
- 在子类找不到,在父类中找到了就是父类的成员方法和成员变量
- 访问到父类的成员方法,其中使用的成员变量名在父类子类中都有,只考虑父类的(不能向下看)
- 写
this.成员方法名
明确地表示访问本类的成员方法和成员变量 - 写
super.成员方法名
,明确地表示访问本类的成员方法和成员变量
- 不写
- 变量区分问题
- 局部变量:
变量名
- 本类成员变量:
this.成员变量名
- 父类成员变量:
super.成员变量名
- 局部变量:
- child class中访问base class中的方法
- 访问父类的成员方法:
super.成员方法名
- 访问父类的构造方法:
super(参数)
- 子类构造方法,才能调用父类构造方法;子类的成员方法不能调用父类的构造方法
super()
只能写在子类构造方法的fisrt statement
- 如果没有写
super(参数)
时,子类中默认调用父类无参构造方法:super()
;- 如果父类中没有写构造方法,编译器默认构造了无参构造方法,子类中默认访问父类无参构造方法
- 如果父类中写了全参构造方法,编译器不再构造无参构造方法,子类中默认访问时会报错,因为找不到父类无参构造方法
- 访问父类的成员方法:
覆盖重写
- 父子类中,方法的名称、参数列表均应该相同;但返回值的类型和权限修饰符允许不同
- 在覆盖重写的方法前,写上注解
@annotation
,进行检测 - 方法覆盖重写的时候,首先考虑子类
子类覆盖重写的方法的返回值的范围,必须小于等于父类方法返回值
Object > String
子类覆盖重写的方法的权限,必须大于等于父类方法的权限修饰符
public > protected > 留空 > private
成员变量不能覆盖重写
- 特点
- 单继承,一个类只能继承一个父类
- 多级继承,子类可以有子类,父类也可以有父类
- 一个子类只能有一个父类,但一个父类可以有多个子类
- (对象的) 多态
- 子类的对象有父类的形态, 父类引用指向子类对象
父类名称 对象名 = new 子类名称();
或接口名称 对象名 = new 实现类名称()
- 成员变量往父类里看: 编译看左边, 运行看左边; 成员方法先从子类里找: 编译看左边, 运行看右边.
- 父类子类有同名的成员变量, 不存在覆盖重写, 而同名成员函数存在覆盖重写!
多态定义下, 通过子类对象访问到的是父类的成员变量和成员函数, 虽然是子类对象也看不到子类的成员变量和方法;
而实例化方式下, 通过子类对象访问到的是子类的成员变量和方法, 如果子类中没有则在父类中查找. - 上下转型
- 向上转型(安全):
父类名 对象名 = 子类对象
创建一个子类对象, 当做父类对象来看; 但问题是调用子类特有方法时不能通过编译, 因为父类引用指向子类对象, 子类对象只能访问父类中的方法和属性
参数列表中要求父类对象, 传入子类对象也可以自动地进行向上转型 (运行时访问子类覆盖重写的成员方法); 如果想要访问特有子类方法的话, 需要判断对象类型childClassObject instanceof ChildClass
, 再向下转型为子类对象. - 向下转型(还原):
子类名 对象名 = (子类名) 父类对象
多态的弊端就是无法使用子类特有的成员属性和成员方法; 所以, 常用 instanceof 判断类型之后, 再进行向下转型
- 向上转型(安全):
- python中操作数据库的SQLAlchemy包, 在写查询/插入数据的函数时就要清楚操作对象的class, 在定义函数的时候参数类型写Base类, 然后再判断该对象对应是什么子类的对象. [参数列表中写父类, 函数内部再用
instance of
判断对象类型] - 抽象方法-abstract
- 返回值类型之前加上 abstract 修饰符;没有方法体,不加
**{}**
,但要加**:**
public abstract 返回值类型 方法名();
- 抽象方法必须对应抽象类,在
class
之前加上 abstract 关键字;抽象类可以有普通的成员方法 - 不能直接 new 抽象类对象
- 必须有子类继承抽象类;子类必须覆盖(@Override)抽象类的所有抽象方法(不加abstract 修饰符)
- 想要继承父类的抽象方法,子类必须也是抽象类
- 默认方法-default
- 返回值类型前加 default 修饰符,有方法体
public default 返回值类型 方法名(参数列表) {方法体}
- 默认方法会被实现类继承;如果不用默认方法,则会导致实现类由于没有重写所有接口的抽象类而需要成为抽象类,进而报错
- 只需要改动接口中的默认方法,而不需要改动实现类;当然实现类也可以覆盖重写接口中的默认方法
- 静态方法-static
- 返回值类型前加 static 修饰符,有方法体
public static 返回值类型 方法名(参数列表) {方法体}
- 不能通过实现类的对象来调用接口当中的静态方法;通过接口名称直接调用静态方法
- 静态方法与对象无关,与类本身有关(思考JVM堆栈工作区中的操作)
- 接口
- 可以定义的内容:常量;抽象方法;默认方法;静态方法;私有方法(允许定义的内容跟JDK版本有关)
- 在类名之前加修饰符 interface;
- 接口中的方法的修饰符默认 public abstract,除非自己加 private,static,default
- 接口中的常量的修饰符默认 public static final,就算不加修饰符也是这个三个;定义的时候必须赋值,因为赋值之后不能修改;常量的命名规则是:全大写,单词之间用下划线链接
- 接口中的方法一定是public的,会被继承
- 使用方法
- 继承父类:
public class 子类名 extends 父类名 {}
- 使用接口:
public class 接口名Impl implements 接口名{}
- 继承父类:
- 接口实现类中必须重写所有的抽象方法,用快捷键
[\alt+\ins]
快捷生成 - 正如不能直接new抽象类对象,也不能直接new接口对象,而应该new接口的实现类对象;因为接口类中没有构造(JDK也不会自动生成构造方法)
- 实现类如果没有重写完接口的方法,等于继承了抽象方法,则它本身需要加 abstract 修饰符成为抽象类
- 关于类的总结
- 普通类之间用
extends
;接口类和实现类之间用implements
- 普通类中的成员变量直接写
数据类型 变量名;
;成员函数可以用abstract, public, private进行修饰- 子类必须重写父类的abstract方法
- 子类可以访问父类的public方法
- 子类无法访问父类的private方法
- 接口类中成员变量要写
public static final 数据类型 变量名 = 数值;
;成员函数的修饰符可以使abstract, public,private,default,static,前三者的使用方法与普通类中的相同- 实现类自动继承接口类的default方法;但也可以覆盖重写接口类的default方法
- 无法通过实现类的对象访问接口类的static方法,只能通过接口类调用
- 【单继承】一个子类只能有一个父类,但一个父类可以有多个子类;
- 【多实现】一个接口可以有多个实现类,且一个实现类可以实现多个接口。
public class InterfaceImpl implements InterfaceA, InterfaceB {}
- 多个父接口中的抽象方法重名,没关系
- 多个父接口中的默认方法重名,必须重写一个带关键字default的方法
- 当实现类继承了父类,并实现了接口,父类和接口类之间的方法有冲突的时候,优先考虑继承父类的方法
public class ChildClass extends BaseClass implements InterfaceClass {}
- 实现类中
- 必须重写全部 abstract method
- 可以重写 default method
- 无法继承和访问 private method
- 不算重写 static method
- final 修饰符
public final class ClassName
限制该类不能有子类public final returnType methodName
限制该方法不能被覆盖重写 (abstract和final不能同时出现, 抽象方法必须覆盖重写, 而final方法不能覆盖重写)final dataType varName
该变量只可以被赋值一次(基本数据类型数据不可变, 引用类型变量中的地址值不可变, 但是其中的数据可以改变)final dataType memberVarName
限制该成员变量必须在声明的时候赋值, 才能避免被赋予默认值.- 权限修饰符
自己什么都能看到 —> 邻居能看到非私有的 —> 儿子能看到公开和受保护的 —> 陌生人只能看见公开的 | | public | protected | (default) | private | | —- | —- | —- | —- | —- | | 类内部 | Y | Y | Y | Y | | 包内部无继承关系 | Y | Y | Y | N | | 不同包有继承关系(导包) | Y | Y | N | N | | 不同包无继承关系 | Y | N | N | N |
- 权限修饰符
- 内部类 (方法能嵌套, 方法不能嵌套)
- 内部类外部类之间不是继承关系, 不能用
super.varName
, 用外部类名.this.varName
访问外部类成员变量 - 内部类随意访问外部类的成员变量/方法
- 外部类访问内部类的需要借助内部类对象 (可以是匿名对象
new 类名()
) - 类内部的”成员内部类”:
外部类名.内部类名 对象名 = new 外部类名().new 内部类名()
- 方法内部的”局部内部类”, 前面不能写修饰符; 局部内部类访问所在方法的局部变量时, 需要该局部变量被final修饰. 这与内存图相关, 局部变量在被调用的时候放入栈, 方法调用结束出栈; 对象放在堆内存中, 等到垃圾回收时才消失.
- 匿名内部类:
接口名称 对象名 = new 接口名称() {/*覆盖重写所有抽象方法*/}
, 方便, 避免为实现类写一个文件; 匿名内部类在创建对象的时候只能用一次, 你们对象在调用方法的时候只能用一次.
- 内部类外部类之间不是继承关系, 不能用
- 基础知识总结
- Java有几种基本类型,分别是哪几种?
- java的基本类型有: 整型(根据所占字节数可分为byte,short, int,long),浮点型(float, double),布尔值boolean,字符char
- 赋值时,整数默认是int,整数后跟L可转为long;浮点数默认是double,浮点数后跟F可转为float.
- Java类修饰符有几种,分别代表什么含义?
- public 公开,可被子类继承
- protected 在不同的包中且无继承关系的情况下,导包也无法访问其成员变量;其他情况与public类似
- private 私有,无法被子类继承或从类外访问
- synchronized 线程安全
- static 静态变量和方法,声明类的时候被放入方法区,所以静态方法中不能出现实力成员变量(比如this,super关键字)
- abstract 抽象方法,不能有方法体,必须被子类或实现类覆盖重写
- default 默认方法,实现类继承接口中的默认方法,不用覆盖重写
- final 修饰基本类型数值和地址不能被更改(常量);修饰引用类型或自定义类的对象,地址值不能被更改
- 接口和类有哪些区别?可以从变量、方法、实例化等角度说明一下吗
- 接口没有构造方法,无法直接被实例化,只能实例化非abstract类型的实现类。而父类子类都可实例化
- 接口的变量默认用public static final修饰,声明时必须赋值;而类成员变量根据有无static修饰分为类成员变量和实力成员变量,声明时不赋值则会有默认初值。
- 接口的方法默认用public abstract修饰,不能有方法体,必须在实现类中覆盖重写。用default修饰则可被实现类直接继承.
- 子类继承父类的所有非private方法,实现类继承接口的所有abstract方法和default方法.
- 子类可继承一个父类, 实现类可以实现多个接口
- Java有几种基本类型,分别是哪几种?