编程软件:IDEA
IDEA编辑常用快捷键
快捷键一: psvm或main —— 用来快速写一个main函数
快捷键二: sout —— 用来快速写一个println函数
快捷键三: fori —— 用来快速写一个for循环
快捷键四: Ctrl+Shift+/ —— 用来快速进行块注释
快捷键五: Ctrl+Shift+/ —— 用来快速取消块注释(与快速进行块注释的按键相同)
快捷键六: Ctrl+/ —— 用来快速进行行注释 例如:在代码中点击某一行,然后按Ctrl+/,就可以对这一行进行注释。
快捷键七: Ctrl+/ —— 用来快速取消行注释(与快速进行行注释的按键相同)
java语法基础
1.关键字
被java语言赋予了特殊含义,用作专门用途的字符串
保留字:现在java尚未使用,但以后版本可能会作为关键字使用。自己使用时应避免使用。
![](https://i-blog.csdnimg.cn/blog_migrate/79a60ede6188b705d170e69269ae4a87.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d0a233d8ea1afb935fb0f964a6940d98.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0851552032006d951efd411ad8704186.png)
![](https://i-blog.csdnimg.cn/blog_migrate/663ad05da2034af0c46d9ab86960c58b.png)
2.标识符
凡是可以自己命名的地方都叫标识符。例如:包名,类名,方法等。
注意: 1.有26个英文字母大小写,0-9,_或$组成。
2.不能以数字开头。
3.不可以使用关键字和保留字,但能包含关键字和保留字。
4.严格区分大小写。
5.标识符不能包含空格。
java中的名称命名规范
1.包名:多单词组成时所有字母都小写:xxxyyyzzz
2.类名、接口名:多单词组成时,所有单词的首字母大写:XxxYyyZzz
3.变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写:xxxYyyZzz
4.常量名:所有字母都大写。多单词时每个单词用下划线连接:XXX_YYY_ZZZ
3.常量
是在程序中的不会变化的数据。
4.变量
内存中的一个储存区域,该区域的数据可以在同一类型范围内不断变化,变量是程序中最基本的存储单元,包含变量类型、变量名和存储的值
作用:方便于运算。因为有些数据不确定。所以确定该数据的名词和存储空间。
特点:变量空间可以重复使用。
在方法体外,类体内声明的变量称为成员变量。
在方法体内部声明的变量称为局部变量。
变量的作用域和生存期:
变量的作用域:
作用域从变量定义的位置开始,到该变量所在的那对大括号结束;
生命周期:
变量从定义的位置开始就在内存中活了;
变量到达它所在的作用域的时候就在内存中消失了;
5.数据类型
-
1.基本数据类型:byte、short、int、long、float、double、char、boolean
-
2.引用数据类型: 数组、类、接口。
数据类型及类型间的转换:
级别从低到高为:byte,char,short(这三个平级)——>int——>float——>long——>double
自动类型转换: 当容量(数值范围)小的数据类型与容量大的数据类型的变量做运算时,运算结果就自动提升为容量大的数据类型
比如:short + int → int,int + long → long,long + float → float,float + double → double
强制类型转换: 强制类型转换是自动类型提升运算的逆运算。强制类型转换的实现需要使用强转符:()
6.运算符
1.算术运算符
%:任何整数模2不是0就是1,所以只要改变被模数就可以实现开关运算。
+:连接符。
++,——
2.赋值运算符
= += —= *= /= %=
3.比较运算符
特点:该运算符的特点是:运算完的结果,要么是true,要么是false。
4.逻辑运算符
& | ^ ! && ||
逻辑运算符除了 ! 外都是用于连接两个boolean类型表达式。
&: 只有两边都为true结果是true。否则就是false。
|:只要两边都为false结果是false,否则就是true
^:异或:和或有点不一样。
两边结果一样,就为false。
两边结果不一样,就为true.
& 和 &&区别: & :无论左边结果是什么,右边都参与运算。
&&:短路与,如果左边为false,那么右边不参数与运算。
| 和|| 区别: |:两边都运算。
||:短路或,如果左边为true,那么右边不参与运算。
5.位运算符:用于操作二进制位的运算符
& | ^
<< >> >>>(无符号右移)
6.三元运算符
语法形式:布尔表达式 ? 表达式1:表达式2
布尔表达式为true,运算结果为表达式1。反之,结果为表达式2。
7.输入,输出语句
-
输入: Scanner input = new Scanner(System.in);
nextInt(), nextDouble(), next(), nextLine()
-
输出: system.out.println() 有换行
8.循环分支
-
分支结构: if switch---break
1.if else语句:
嵌套else就近原则
if ();后面不能加 ;
2.switch 语句:
case:类型相同,且为常数
break:跳出循环
default 可选项,无符合条件case时执行
-
循环结构: for while do while---- continue break
foreach语句是for语句特殊情况下的增强版本,简化了编程提高了代码的可读性和安全性不用怕数组越界。
相对老的for语句来说是个很好的补充,提倡能用foreach的地方就不要再用for了。
在用到对集合或者数组索引的情况下foreach显得力不从心这个时候是用for语句的时候了, foreach一般结合泛型使用
for(元素类型type 元素变量value :遍历对象obj){
引用x的java语句`
}
数组
1.概念
数组是可以存储同一种数据类型多个元素的集合,也可以看成是一个容器
数组既可以存储基本数据类型,也可以存储引用数据类型
2.创建和初始化
格式:elementType[] arrayRefVar = new elementType[arraySize]
静态初始化:给出初始化值,由系统决定长度
数据类型[] 数组名 = new 数据类型[]{元素1,元素2,...};
动态初始化:只指定长度,由系统决定初始化值
数据类型[] 数组名 = new 数据类型[数组的长度];
3.遍历
利用循环遍历数组
//for:
for (int i = 0; i < args.length; i++) {
System.out.println(args.length);
}
//foreach:
for(elementType element:arrayRefVar){
System.out.println(e)
}
4.方法中传递数组
对于基本数据类型参数,传递的是实参的值
对于数组类型参数,传递的是数组的引用
5.多维数组
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。
二维数组:数据类型[] 数组名 = new 数据类型[数组的长度i][数组的长度j];
public static void araryDeclareCreateInitializer() {
// Java 中数组既不是对象也不是基本数据类型。而是一种储存数据的方式
double[] myList1; // 声明数组 myList1,不分配内存空间,只是创建引用位置:仅只是定义一个变量
// int myList[]; // 兼容c
myList1 = new double[10]; // ---------创建数组
double[] myList2 = new double[20]; // --------声明+创建
// 声明数组变量myList2,创建20个元素构成数组,将数组引用赋值给myList2
// 相当于上面两句
myList1[0] = 1.1; // --------数组初始化
myList1[1] = 1.2;
System.out.println(myList1[0] + "---");
double[] myList3 = {1.1, 1.2, 1.3, 2.1}; // ------- 声明,创建,初识化在一条语句
}
方法
1.概念
方法是语句的集合,它们在一起执行一个功能,本意是功能快,就是实现某个功能的语句块的集合
方法是解决一类问题的步骤的有序组合
方法包含于类或对象中
方法在程序中被创建,在其他地方被引用
2.定义
方法包含一个方法头和一个方法体,下面是一个方法的所有部分:
修饰符:可选的,告诉编译器如何调用该方法
返回值类型:方法可能会有返回值。returnValueType是返回值类型
方法名:实际名称,和参数表共同构成方法签名
参数类型:参数像是一个占位符。当方法被调用时,传递值给参数,这个值称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数
形参:在方法被调用时用于接收外界输入的数据
实参:调用方法时实际传给方法的数据
方法体:方法体包含具体的语句,定义该方法的功能
修饰符 返回值类型 方法名(参数类型 参数名){
//例public static returnValueType methodName(list of para)
...
方法体
...
return 返回值;
}
3.调用和重载
构成重载:
方法名相同
-
参数个数不同
-
参数类型不同
-
参数顺序不同
不构成重载:编译错误
-
只有返回值不同 public int add(int n1,int n2) public double add(int n1,int n2)
-
只有参数名称不同 public int add(int n1,int n2) public int add(int n2,int n1)
public static void main(String[] args) {
max(1,2); //方法调用
max(1,2,3);
}
public static int max(int a,int b){ //方法定义
if (a>b) return a;
else return b;
}
public static int max(int a,int b,int c){ //方法重载
if (a>b&&a>c) return a;
else if(b>a&&b>c) return b;
else return c;
}
4.可变参数
typeName...parameterName(类型名...参数名) 参数个数可变
值传递,变量值不改变 (注:参数是数组时,会改变数组值)
封装
1.概念
将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互,是面向对象三大特征之一
-
访问限定符
![](https://i-blog.csdnimg.cn/blog_migrate/32d6a9573581ae1425746a1dca16a137.png)
3.内部类
可以将一个类的定义放在里另一个类的内部,这就是内部类。内部类分为四种:成员内部类、静态内部类、局部(方法)内部类、匿名内部类。
内部类访问特点:
-
内部类可以直接访问外部类的成员,包括私有
-
外部类要访问内部类的成员,必须创建对象
成员内部类
-
在类的成员位置
-
可以是任何的访问修饰符。
-
内部类的内部不能有静态信息。
-
内部类也是类,继承、重写、重载注意使用,this和super可以任意使用。
-
外部类要访问内部类信息,必须使用new之后访问。
-
内部类可以直接使用外部类的任何信息,如果属性或者方法发生冲突,调用外部类.this.属性或者方法。
外界访问时的格式: 外部类名.内部类名 对象名 = 外部类对象.内部类对象
代码示例:
public class Outer {
private int num=10;
public class Inner{ //成员内部类
public void show(){
System.out.println(num);
}
}
//可以使用这种类型,通过内部类的另一方法访问
private class Inner2{
public void show(){
System.out.println(num);
}
}
public void method2(){ //访问私有Inner2类
Inner2 i=new Inner2();
i.show();
}
}}
public class Demo {
public static void main(String[] args) {
Outer.Inner a=new Outer().new Inner(); //第一种方法
a.show();
Outer o=new Outer(); //第二种方法
o.method2();
}
}
静态内部类
-
内部可以包含任意的信息。
-
静态内部类的方法只能访问外部类的static关联的信息。
-
访问内部类的静态信息,直接外部类.内部类.静态信息就可以了。
-
静态内部类可以独立存在,不依赖于其他外围类。
格式: 外部类.内部类 引用=new 外部类.内部类()
public class Outer {
private int num=10;
public static class Inner{ //静态内部类
public void InnerShow(){
System.out.println("静态内部类成员方法被调用");
}
public static void InnerShow2(){
System.out.println("静态内部类静态方法被调用");
}
}
}
/*
测试类
*/
public class Demo {
public static void main(String[] args) {
Outer.Inner.InnerShow2(); //访问静态内部类的静态方法
Outer.Inner o=new Outer.Inner(); //访问静态内部类的成员方法
o.InnerShow();
}
}
局部内部类
-
在类的局部位置
-
在方法中定义的类,所以外界是无法直接使用,需要在方法内部创建对象并使用
-
该类可以直接访问外部类的任何信息,也可以访问方法内的局部变量和参数
-
类前不能有访问修饰符。
-
无法创造静态信息。
代码示例:
public class Outer {
private int num=10;
public void method(){
int num2=20;
class Inner{ //局部内部类
public void show(){
System.out.println(num);
System.out.println(num2);
}
}
Inner i=new Inner(); //需要在方法内部创建对象并使用
i.show();
}
/*
测试类
*/
public class Demo {
public static void main(String[] args) {
Outer o=new Outer();
o.method();
}
}
/*
输出结果:
10
20
*/
匿名内部类
-
前提:存在一个类或者接口,这里的类可以是具体类也可以是抽象类
-
本质:是一个继承了该类或者实现了该接口的子类匿名对象
-
匿名内部类没有访问修饰符
-
匿名内部类没有构造方法
-
使用匿名内部类时,这个new之后的类首先是要存在的,其次我们要重写new后的类的某个或某些方法
-
匿名内部类访问方法参数时也有和局部内部类同样的限制
格式: new 类名或者接口名(){
重写方法
}; //注意结尾要分号
代码示例:
public interface Inner2 { //接口
void show();
}
public class Outer {
private int num=10;
public void method(){
int num2=20;
new Inner2(){ //匿名内部类 第一种输出
@Override
public void show() {
System.out.println("匿名内部类");
}
}.show();
new Inner2(){ //两次输出
@Override
public void show() {
System.out.println("匿名内部类");
}
}.show();
Inner2 in= new Inner2(){ //第二种输出
@Override
public void show() {
System.out.println("匿名内部类");
}
};
in.show();
}
}
/*
测试类
*/
public class Demo {
public static void main(String[] args) {
Outer o=new Outer();
o.method();
}
}
继承
1.概念
继承是面向对象三大特征(封装、继承、多态)之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义,追加属性和方法
2.注意事项
-
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模
-
extands的意思是“扩展”, 子类是父类的扩展
-
java中类只有单继承,没有多继承
-
继承是类和类之间的一种关系,类和类的之间的关系还有依赖、组合、聚合等
-
继承关系的俩个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键=字extends来表示
-
子类和父类之间,从有意义上讲有“is a”的关系
-
super关键字:
super调用父类的构造方法,必须在构造方法的第一个
super必须只能出现在子类的方法的或者构造方法中
super和this 不能同时调用构造方法
VS this:
代表的对象不同:
this:本身调用者
super:代表父类对象的应用
前提不同:
this:没有继承可以使用
super:只能在继承条件下才可以使用
构造方法不同:
this():本类的构造
super():父类的构造
3.利弊
好处:提高了代码的复用性(多个类相同的成员可以放到同一个类中)
提高了代码的维护性(如果方法的代码需要修改,修改一处即可)
弊端:继承让类与类之间产生了关系,类的耦合性增强了,当父类发生变化时子类实现也不得不跟着变化,削弱了
子类的独立性
4.变量的访问特点
在子类方法中访问一个变量:
先在子类局部范围找
再在子类成员范围找
然后在父类成员范围找
如果都没有就报错
5.构造方法的访问特点
子类中所有的构造方法默认都会访问父类中无参的构造方法:
-
因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化
-
每一个子类构造方法的第一条语句默认都是super()
如果父类中没有无参构造方法,只有带参构造方法:
-
通过使用super关键字去显示的调用父类的带参构造方法
-
在父类中自己提供一个无参构造方法
6.成员方法的访问特点
通过子类对象访问一个方法
子类成员范围找
父类成员范围找
如果都没有就报错
7.方法重写
子类中出现了和父类一模一样的方法声明。
应用:当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容。
代码示例
public class Fu {
private int age;
public Fu() { //父类无参构造方法
System.out.println("fu中无参构造方法被调用");
}
public Fu(int age) { //父类带参构造方法
this.age = age;
System.out.println("fu中带参构造方法被调用");
}
public int getAge() { //getAge 成员方法
return age; //便于外界访问age
}
public void setAge(int age) { //setAge 成员方法
this.age = age; //this调用本身的私有成员变量
}
public void show(){ //show方法
System.out.println("fu中show方法被调用");
}
}
public class Zi extends Fu{
public Zi() { //子类无参构造方法
//super(); 默认调用
System.out.println("zi中无参构造方法被调用");
}
public Zi(int age) { //子类带参构造方法
super(age); //调用父类带参构造方法
}
@Override
public void show() { //重写父类的show方法
super.show();
}
}
/*
测试类
*/
public class Demo {
public static void main(String[] args) {
Zi z1=new Zi(); //创建子类对象,调用子类无参构造方法,由于继承关系,会先调用父类无参构造方法
System.out.println("--------");
z1.setAge(20);
System.out.println(z1.getAge());
System.out.println("--------");
Zi z2=new Zi(19); //创建子类对象,使用子类带参构造方法
System.out.println(z2.getAge());
System.out.println("--------");
z2.show();
/*
输出结果:
fu中无参构造方法被调用
zi中无参构造方法被调用
--------
20
--------
fu中带参构造方法被调用
19
--------
fu中show方法被调用
*/
}
}
静态static
static修饰的成员变量和方法,从属于类
普通变量和方法从属于对象
静态只能用静态
静态方法优点:不需要new对象,直接采用类名调用,极其方便
声明变量为实例或静态:如果这个类型的所有对象的某个属性值都是一样的,不建议定义为实例变量,浪费内存空间。建议定义为类级别特征,即静态变量,在方法区中只保留一份,节省内存开销。
定义方法为实例方法或静态方法:1.如果该方法必须由对象去触发,则定义为实例方法 2.在方法体中,直接访问了实例变量,则一定是实例方法 在开发中,工具类中的方法一般是定义为静态的
常用类
1.数学类Math
三角函数
-
sin(弧度) 返回正弦函数值
-
cos(弧度) 返回余弦函数值
-
tan(弧度) 返回正切函数值
-
toDegrees(弧度) 弧度转化为度
-
toRadians(度) 度转化为弧度
-
asin() 返回反正弦函数值
-
acos() 返回反余弦函数值
-
atan() 返回反正切函数值
指数函数
-
exp(x) 返回e的x次方
-
log(x) 返回x的自然底数
-
log10(x) 返回x的以10为底的对数
-
pow(a,b) 返回a的b次方
-
sqrt(x) 返回x的平方根(x>=0)
取整方法
-
ceil() 向上取整
-
floor() 向下取整
-
rint() 取整最接近的整数
-
round() 四舍五入
min,max,abs,random方法
-
min() 最小值
-
max() 最大值
-
abs() 绝对值
-
random() 随机数(0<=random<1)
2.单个字符类Character
-
isDigit() 判断是否为数字
-
isLetter() 判断是否为字母
-
isDigitorLetter() 判断是否为数字或字母
-
isUpperCase() 判断是否为大写字母
-
isLowerCase() 判断是否为小写字母
-
toUpperCase() 转为大写
-
toLowerCase() 转为小写
3.字符串类String
-
length() 返回字符长度
-
charAt() 返回指定位置字符
-
concat(s1)) 两字符串拼接
-
toLowerCase()) 全部小写
-
toUpperCase()) 全部大写
-
trim() 去除两边空格
-
equals() 判断是否相等
-
equalsIgnoreCase() 判断是否相等(不区分大小写)
-
subString() 返回两下标间的字符串
-
indexOf() 获取字符串的下标
4.日期类Date
-
构造方法:
无参构造 public Date():分配一个Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒
带参构造 public Date(long date):分配一个Date对象,并将其初始化为表示 从标准基准时间起 指定的毫秒数
public static void main(String[] args) {
Date d1=new Date();
System.out.println(d1); //返回当前时间
long l=1000*60*60;
Date d2=new Date(l);
System.out.println(d2);
}
-
常用方法:
public long getTime(), 获取的是日期对象从1970年1月1日 00:00:00到现在的毫秒值
public void setTime(), 设置时间看,给的是毫秒值
public class DateDemo {
public static void main(String[] args) {
Date d=new Date(); //创建日期对象
System.out.println(d.getTime());
System.out.println(d.getTime()*1.0/1000/60/60/24/365+"年");
long time=System.currentTimeMillis();
d.setTime(time);
System.out.println(d);
long time2=1000*60*60;
d.setTime(time2);
System.out.println(d);
}}
-
SimpleDateFormat类: 简单日期格式
构造方法:
public SimpleDateFormat(): 构造一个SimpleDateFormat,使用默认模式和日期格式
public SimpleDateFormat(String pattern): 构造一个SimpleDateFormat使用给定的模式和默认的日期格式
年:y 月:M 日:d 时:H 分:m 秒:s
格式化: 从Date到String
public final String format(Date date): 将日期格式化为日期/时间字符串
解析: 从String到Date
public Date Parse(String source): 从给定字符串的开始解析文本以生成日期
代码示例:
public static void main(String[] args) throws ParseException {
//格式化: 从Date到String
Date d=new Date();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String s=sdf.format(d);
System.out.println(s);
//解析: 从String到Date
String ss="2022-09-26 22:00:54";
SimpleDateFormat sdf2=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //注意要对应 否则报错
Date dd=sdf2.parse(ss);
System.out.println(dd);
}
包装类
包装类与基本数据类型的区别:
-
声明方式不同,基本类型不用new创建,封装类需要
-
存储方式和位置不同,基本类型直接存储变量的值保存在堆栈中,能高效的存取;封装类型需要通过引用指向实例,具体的实例保存在堆中
-
初始值的不同,封装类型的初始值为null,基本类型的的初始值视具体的类型而定,比如int类型的初始值为0,boolean类型为false;
什么时候用
-
字段是否允许null值,如果允许null值,则用包装类
-
用到比如泛型和反射调用函数,就需要用包装类
-
在使用集合类型时,就一定要使用包装类型,因为容器都是装object的,基本数据类型显然不适用
自动装箱:通过调用包装类的valueOf()方法实现的
Integer i=100; //Integer i=Integer.valueOf(100)
自动拆箱:通过调用包装类的xxxValue()方法实现的,xxx表示对应基本数据类型,如intValue()、doubleValue().
Integer i=100;
int j=i; //int j=i.intValue()
枚举类
枚举类型隐性地继承自java.lang.Enum,实质上是个类,每个被枚举的成员实质是一个枚举类型的实例,默认是public static final修饰,可以直接用枚举类型名使用它们
建议:
-
需要定义一组常量时,可以使用枚举类型
-
尽量不要使用枚举的高级特性,事实上高级特性可以直接使用普通类实现,没必要用枚举,提高复杂性
enum 枚举名{
枚举体(常用列表)
}
//示例
enum Season{
春,夏,秋,冬
}