*.java java源文件 该文件中存储所有的java源代码
在java中一切皆对象,所以一切属性和方法必须定义在类(class关键字)中
源文件名称必须与主类名称一致,主方法存储在主类中。
javac编译器 ——将源文件编译成字节码文件也就是class文件,然后class文件通过java解释器翻译为具体操作的机器码给机器执行。
JDK——java开发工具包,包括jre开发环境以及开发工具,比如javac编译器
JRE——java运行时环境,包括jvm与javase标准类库
JVM——java虚拟机,保证java 做到 write once,run everywhere的关键
添加的注释在编译后是不存在的,只存在于源文件中。
标识符:在程序中给类、方法、变量取的名字都叫标识符,取名规则为:可以包含字母、数字、下划线以及美元符$(不推荐)。不能以数字开头,不能使用java中的关键字,区别大小写(java中一切都区分大小写)。
关于标识符的命名:驼峰命名法:类名用大驼峰,每个单词首字母都大写,class TestStudent;方法和变量使用小驼峰:第一个单词首字母小写,其他都大写:int myAge = 10.
八大基本数据类型分别为:数值型:byte short int long (整型)float double (浮点型)
字符型:char 布尔型:boolean 其中数值型整型的默认值为0,浮点型默认值为0.0,字符型默认值为\u0000,boolean型默认值为false。
三大引用类型分别为:类、数组与接口,他们的默认值为null。特别的。所有引用数据类型的变量,保存的都是存储内容的地址,并非实际的内容。另外,当引用数据类型的值为默认值null时,表示不指向任何对象,无法通过该引用数据类型进行任何操作,操作的话会产生NPE错误。
特别提醒:所有的数据类型只有在类中定义时才具备默认值,在方法中的局部变量是不具备默认值的。你在类中定义时可以写 int a而不赋值不会报错,但是你在方法中调用时或创建局部变量时写 int a 就不行,必须在使用前赋值。
程序中有两种类型的数值,一种为变量,定义后可以修改该变量的具体数值,另一种为常量,数值无法改变,用final修饰。
变量语法:数据类型 变量名称 = 初始值 eg:int a = 10
一行中可以定义多个对象:int a = 10,b = 20 ,c;特别的 如果为int a,b,c=10;此时只有c为10,a和b为默认值,要特别注意
因为java中一切皆对象,所以一切都可以用类来描述,但八大基础数据类型不属于类,为了满足一切皆对象原则,为八大基础数据类型创建了包装类,这样它们也就能成为对象了。包装类除了int的为Integer,char为Character之外,其他的均首字母大写即可。
在进行数据处理时,得出的最终结果要与数据类型匹配,如果不匹配就会出现精度损失。如果int / int 那么得到的还是int ,如果结果是小数那么会舍去小数点后的数字以此来输出int的结果。
字面量:直接展示出来的就是字面量,比如10 (整型字面量),abc(字符串字面量),他们都是常量,因为10只能指代10,abc只能指代abc,在使用时,int a = 10相当于把一个10的字面量常量赋值给了变量a。另外,整型字面量默认为int类型,浮点型字面量默认为double。
关于类型转换与类型提升:小类型转为大类型自动转换,大类型转小类型需要强制转换。因此
float = 10.1F(大转小强转) long b = 10(小转大自动),并且在运算时,小数据类型与大数据类型一起计算,自动将小类型提升为大类型再计算。
另外,存储byte short char的时候看它本身大小,但是调用时默认将其调为int类型进行处理。
java中任何数据类型与字符串(string类)进行+操作,都会变成拼接结果。
string类中有一个valueOf方法可以将纯数字字符串转换为数值型,接收该数值的数据类型必须比转换过来的数值要大,否则放不进去。
算术运算符:+ - * / %(取余)+= -= *= %= (先进行=前的运算再得出结果,例如 1 +=2,就为3)
关系运算符:== != < > <= >= 计算结果为布尔值,该运算符的意思为:判断数据怎么怎么样(根据具体运算符来决定, ==就是判断两个数据相等,相等为true不相等为false,!=为判断不相等)
逻辑运算符:&& (逻辑与)并且关系 || (逻辑或)或者关系 运算结果也为布尔值 特别的!为逻辑取反
位运算符:在二进制位进行操作 &(按位与) |(按位或) ^(按位异或) ~(按位取反)
&:二进制位(后同)都为1返回1否则0 | :都为0返回0否则1 ^ :相同返回1不同返回0 ~:1变为0 ,0变为1
>> 与<<分别是在二进制位右移和左移,空出的位置补0。特别的,当一个数<<1(二进制位左移一位)相当于*2,>>1相当于/2.
条件运算符:三目运算符(条件判断的一个简化写法):语法:表达式1?表达式2:表达式3(1true执行2false执行3)
分支结构if语法(三种):
if (布尔表达式){
满足条件时执行的语句
}…………第一种
if (布尔表达式){
满足条件时执行的语句
}else{
不满足时执行的语句
}…………第二种
if (布尔表达式1){
满足布尔表达式1时执行的语句
}else if(布尔表达式2){
满足布尔表达式2时执行的语句
}else{
都不满足执行的语句
}…………第三种
十分重要的点:;分号代表语句结束!!!!!!
switch分支的语法:
switch(表达式:int以及小于int的char short byte,string,枚举){
case 字面量1:{
匹配字面量1时的语句
}
case字面量2:{
匹配字面量2时的语句
[break];
}
default:{
以上case都不匹配时执行的语句;
[break];
// break表示switch语句到此为止,不加则会往下跑,case1没加就会往下到case2
}
}
while循环语法结构(知道终止条件首选):
while(循环满足的条件:必须为布尔表达式){
满足时执行的循环语句
tips:记得更新循环条件
}
循环中的break:跳出当前循环
循环中的continue:在该处跳出这一次循环直接进行下一次
for循环语法结构(知道循环次数首选):
for(表达式1;布尔表达式;表达式3){
循环语句
}
其中表达式1为初始化变量,布尔表达式2为循环判断的依据,满足就循环,表达式3为循环变量更新的表达式
加强for循环语法结构:
for(数据类型 变量名 :遍历的目标){
//数据类型 变量名:声明一个变量用来接收遍历目标遍历后的元素
} //可以用于数组的元素遍历
从系统中输入数据,使用Scanner类,先创建一个scanner对象:
语法:Scanner sc = new Scanner(system.in);
然后调用该类中的方法 nextLine方法(从键盘获取字符串)nextInt(获取整数) nextDouble(获取小数)
方法的定义语法(必须定义在类中):
修饰符 返回值类型 方法名称(参数类型 形参名称){
方法体代码
[return返回值]; //当反回值类型为void时,没有返回值,不写return语句
}
调用方法:方法名称(参数)
形参为定义方法时定义的,此时并没有具体的数值,而实参则为调用方法时赋的具体的值,执行的操作为实参数据拷贝,赋值给形参。
实参和形参储存在不同的栈帧中,在对形参的数值进行操作时,不会影响到实参的数据。
方法重载(overload):在同一个类中,定义了若干方法名称相同,参数列表不同(参数类型或个数),与返回值无关的一组方法。是一种静态绑定,根据传参不同来调用方法。方法覆写则是动态绑定。
根据方法的定义语法,如果方法一和二是重载方法,那么应该是这样的:
方法一:
修饰符 返回值类型1 方法名称a (参数类型1 形参名称 参数类型2 形参名称){
}
方法二:
修饰符 返回值类型2 方法名称a (参数类型3 形参名称 ){
}
//方法一和二参数类型与参数个数都不一样,但是方法名称是一样的,且与返回值无关,此处返回值不同,相同的话也可以
方法递归:方法在执行过程中又调用自身的过程,称为递归。使用递归要满足以下三个条件:
1 一个大问题可以拆分为若干个小问题
2拆分后的子问题与原问题除了数据规模不同之外,解决的思路完全相同
3存在递归终止条件,即分到什么时候不用分也能得出结果
递归实质运行起来就是一个往下一层一层递下去再一层一层返回处理的过程(有些不用返回,没有返回值的可以理解为一个循环,因为上层执行语句的时候不需要返回值参与)
数组:一种引用数据类型,相同数据类型数据的集合,数组存储在内存中连续空间。数组为引用数据类型,存储在堆中。一旦创建长度确定不可更改。
语法:数组的静态初始化(元素已确定):数据类型 [ ] 数组名称 = { 元素值1 ,元素值2,……}
静态初始化在编译时会产生new关键字,此处为Java语法糖,舍去了。
数组的动态初始化(元素未确定):数据类型 [ ] 数组名称 = new 数据类型 [数组长度]
new关键字在任何地方出现都是指在内存堆中开辟空间存放东西
数组内的元素下标从0开始,表示对首元素的偏移量,数组内元素个数为N则下标最多为N-1.
访问数组中的元素使用 数组名称 [ 下标 ]
得到数组长度用 数组名称.length
数组的元素遍历(不更改数据):for - each循环(上文中的增强for循环) for (int i ,num1){}
数组的冒泡排序:当前一个元素大于后一个元素,交换两个元素的位置,然后比较后面两个,一直走到底。
数组的拷贝:Arrays.copyOf(原数组名称 , 新数组长度)//数组工具类Arrays中的copyOf方法
数组问题的双引用解法:通过设定左边界与右边界的方式,通过一些操作加边界移动来达到解决问题的解法。
类的定义:使用关键字class来定义,类只是一个模板,没有具体意义,不是具体实例。
class 类名称 {
属性:成员属性,对象属性
方法:成员方法,对象方法
}
一个源文件只能存在一个主类,主类名与源文件名相同。
类的实例化:
类名称 引用名称(实例对象的名称) = new 类名称();//此处的 类名称()括号内内容要根据具体构造方法填入,例如构造方法中为 类名称 (int a ,int b )那么在使用实例化创建对象时也要存入相应的参数。
通过该实例对象就可以使用 “ . ”操作符访问成员属性和成员方法。
引用名称 . 成员属性/成员方法名称
构造方法:初始化对象要用构造方法,其就是为了产生对象,给对象做初始化操作。
构造方法的特点:
1 构造方法与类名称相同,无法自定义方法名称
2 构造方法没有返回值类型声明,void
3 构造方法在产生对象时由编译器自动调用并且只在产生对象时调用一次。
语法:
类名称 (参数){
构造语句
}
如果没有构造语句和参数则为无参构造。在你创建一个类时,如果你不写构造方法,编译器会自动生成一个无参构造,如果你写了,那么该无参构造就不会生成。
成员变量的所有赋值操作都在构造方法中进行。
构造方法也是可以重载的,此时只是参数个数不同,因为类型已经定义过了。
this关键字的使用:
1 this修饰成员变量 :this.属性名称 表示直接从类中寻找同名变量,防止编译器的就近匹配原则产生bug。
2 this修饰方法:修饰成员方法:表示调用类中的成员方法。 this.方法名称
当有继承关系后,明确调用的是当前类的成员方法,加上this
调用构造方法: this(参数);(构造方法之间才能相互调用)这种调用体现在,当一个构造方法是另一个构造方法的一部分时,可以调用this(参数)直接调用那部分构造方法,然后再写其他的语句。
3 this表示当前对象的引用:在语句中出现this时,当前方法或属性是哪个实例对象调用的,那么这个this就指代那个实例对象。
static关键字的使用:
static与具体实例对象无关,是静态的,与类有关。
staitc修饰属性,称为类属性,静态属性,存放在JVM的方法区,类属性在没有对象时(即指代值为null时也可以使用,但是成员方法和成员变量不可以)也能使用。
java中不支持在方法中定义静态变量,方法中定义的都是局部变量。
静态属性通过类名称直接调用: 类名称.静态属性名称
static修饰方法:类方法,直接通过类名称调用: 类名称.类方法名称
static无法修饰外部类,但是可以修饰内部类。
static变量的初始化:就地初始化(定义静态变量时就直接初始化)或在静态代码块中初始化。
四种代码块:
普通代码块:直接定义在方法内部,不加任何修饰符定义的代码块 { } ;代码块内部就是各个变量的作用域
构造块:直接定义在类中,{ }内的代码块 特别的 构造块优先于构造方法执行
静态代码块:一般用于初始化静态变量 使用static修饰,直接定义在类中的代码块。在类加载时执行一次。特别的,主类中的静态代码块会优先于主方法执行。
同步代码块:使用synchronized(){}包裹起来的代码块,在多线程环境下,对共享数据的读写操作是需要互斥进行的,否则会导致数据的不一致性。同步代码块需要写在方法中。
面向对象三大特性:封装、继承与多态
四大权限修饰符:private default protected public
需要注意的是,权限修饰符指的是在哪些类中可见,与具体对象无关。
private 修饰符:私有属性,只在当前类内部可见。当属性方法被封装之后,外部只能通过设定的getter 与 setter (必须满足设定的条件)来获取和修改私有属性。
default 修饰符:包访问权限,当前包内部可见(子包不行)。什么都没写就默认是包访问权限,包就是文件夹。包的命名:全小写,单词之间用_分割。使用 import关键字来导入某个包下的某个类。使用 import java. 包名,类名 导入。 另外不确定导入的是一个包中的哪个类时,可以使用通配符:import java. 包名,* ,这样它就会自动根据调用的类来导入该包下相对应的类。特别的,这种通配符有重名的隐患,因此还是建议写全名。
静态导入::将一个类1的所有静态域导入到当前类2中,和之前唯一的区别就是在类2中调用类1的方法属性不需要加类1前缀。
protected修饰符:在不同包的具有继承关系的类中可见。
类和类之间的关系有继承和组合。
继承的使用要满足 is - a原则:子类 is a 父类。
*组合关系:has -a 原则 父类 has a子类。
继承的语法:使用extends表示继承父类:访问修饰符 class 子类名称 extends 父类名称
当在子类中访问变量,访问的变量在子类中存在时,优先调用子类的,不存在时,调用父类的。
特别的,父类中存在私有域属性与方法,只能被隐式继承,无法在外部被调用。
当通过子类对象调用方法时,子类中存在则调用子类的,否则调用父类的(私有域无法被调用)。
要注意的点为:要根据方法名称+参数来确定是调用的方法
当用构造方法产生子类对象时,默认先用父类构造方法产生父类对象。
子类中若想直接跳过子类属性和普通方法调用,则使用super关键字直接在父类中寻找对象。
特别的,我们知道当用构造方法产生子类对象时,默认先用父类构造方法产生父类对象。在父类中构造方法为无参构造时,不需要在子类的构造方法首行写上super(参数);来表示调用父类的构造方法,但是父类构造方法如果不是无参构造,那么必须在子类构造方法首行写上super(参数);来表示调用了父类的构造方法。
Java的单继承局限:不允许多重继承,即一个子类继承多个父类(但是接口可以!)。
java继承支持的几种方式: 单继承(a继承b)多层继承(a继承b,b继承c)不同类继承同一个类(a继承c b继承c)
final关键字:终结器,该关键字修饰的全部都为常量,初始化后值不可更改。
修饰基本数据类型时,必须先赋值再使用,赋值的内容不可变。修饰引用数据类型时,不变的常量为地址,其指向的内容还是可变的。
final修饰方法:不可被覆写 修饰类:不存在子类
多态:同样的方法,不同的对象,展现出不同的行为结果。
要实现多态,必须满足以下三个条件:
1多态的实现依赖于继承,只有在继承体系下才有多态
2子类必须覆写父类的方法
3通过父类引用调用子类覆写的方法
方法覆写:在有继承关系的类之间,子类定义了和父类除了权限不同以外,其他(方法名称,参数列表,返回值(向上转型除外))完全相同的方法,称为子类覆写了父类的方法。特别的,子类的权限>=父类的权限。
方法覆写是一种动态绑定:编译时不确定用哪个对象的方法,只有在运行时,根据具体传入方法的对象,才能知道到底调用的是哪个方法。
向上转型:天然发生的,也是产生对象的主要使用方式
语法:父类名称 父类引用 = new 子类实例(参数)
这里非常重要的点是 产生该向上转型的对象,通过该父类引用该能调用哪些方法和属性,是父类决定的,而至于调用这个方法到底表现出什么行为是new的子类对象决定的。如果子类覆写了则调用子类中覆写的方法,如果没有则执行父类中的。并且子类中独有的属性方法无法调用。
向上转型的优势是参数统一化,缺点是子类中独有的无法调用。
想调用则使用向下转型(必须先发生向上转型,否则实现不了):
子类名称 子类引用 = (子类名称)父类引用
可以使用java中instanceof关键字来判断一个父类引用是否指向一个子类对象(向上转型)
语法:引用名称 instanceof 类 ( 返回布尔值)
快捷方法:
快速生成main方法:psvm
快速生成打印函数:sout
快捷将选中的部分注释或反注释 ctrl +/
快捷生成for循环:fori
快捷生成构造方法 Alt+enter ,然后属性全选Alt+A,单个Alt鼠标左键点击