在学习java的时候遇到了很多问题,在这里汇总一下,同时会有一些自己的理解,可能会有些错误,欢迎各位大佬给出建议和指正错误。
异常
InputMismatchException
原因:输入不匹配异常,即输入的值数据类型与设置的值数据类型不能匹配。
在输入数据时,把sc.nextInt()赋值给了一个小数类型的变量。
解决方法:float a = sc.nextFloat();
异常处理方式
多异常处理
try{
可能发生异的代码
}catch(异常类型1|异常类型2|异常类型3 e){
共用的处理方式
}
try…catch…finally
try{
可能发生异常的代码
}catch(可能出现异常的类型 异常对象){
异常类型的处理方式
}finally{
无论有无异常都一定要执行的代码
}
try…finally
try{
可能发生异常的代码
}finally{
一定要执行的代码
}
try…finally…无法捕获和处理异常,一般适用于有两句代码,并保证第一句代码的执行与否不会影响到第二句代码的执行,若发生异常按照jvm默认的处理方式处理。
在类中调用方法
一个静态方法可以被其他的静态或非静态方法直接调用;
public static void main(String[] args){
//在静态的main方法中,能直接调用同样是静态的方法
int a=1;
int b=2;
int c=sum(a+b);
}
public static int sum(int a,int b){
return a+b;
}
public int sum(int a,int b,int c){
int d = sum(a+b);//非静态方法可以直接调用静态方法
returen d+c;
}
一个非静态方法可以被其他非静态方法直接调用。
而一个非静态方法只有通过对象才能被其他静态方法调用。
public class Test4 {
public static void main(String[] args) {
int[] a = {1,2,3,4,5};
System.out.println("平均值:");
avg(a);//平均值
System.out.println("a+b:");
System.out.println(sum(1, 2));
System.out.println("a+b+c:");
Test4 t = new Test4();//通过对象调用非静态方法
System.out.println(t.sum(1, 2, 3));
}
public static int sum(int a,int b){
return a+b;
}
public int sum(int a,int b,int c){
int d = sum(a,b);//非静态调用静态
return a+b+c;
}
public static void avg(int[] a){
int sum=0;
for (int i = 0; i < a.length; i++) {
sum=a[i]++;
}
}
}
Random随机数
Random r = new Random();
int a = r.nextInt(int n);
nextInt(int n) n代表一个参数,表示要生成的随机数范围,此方法生成的范围[0,n),包含0,不包含n,又因为随机数是整数,所以实际范围0~n-1
数组
1、int[] ages = {10,20,30,21,23,24,25,26,26};
每个元素都有自己的编号,通过数组名+容器编号,可以定位到每一个数据
2、数组的特点:
存储数据类型一致的数据,而且数组是一个定长的容器,必须指定数组的大小,代表存储元素的个数
数组的动态初始化:
数据类型[] 数组名 = new 数据类型[数组长度];
数据类型 数组名[] = new 数据类型[数组长度];
int[] age = new int[5];
int ages[] = new int[5];
数组的遍历
一般的遍历:
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]+"\t");
}
数组也可以用增强for循环来进行遍历
数据类型
String类型
String类型的获取功能
1、length():获取一个字符串中的字符个数,返回值int
2、charAt(int index):将字符串指定index索引上的字符,获取到,返回值是char
3、subString(int beginIndex):截取字符串中的一部分,返回一个新的字符串,从beginIndex索引开始到后面的所有的字符
4、subString(int beginIndex,int endIndex):从begin位置开始到end-1之间的字符进行截取,形成一个新的字符串,截取叫做含头不含尾
5、indexOf(String str):获取参数字符串str在方法调用的字符串中,第一次出现的索引位置,返回值是int,如果没有找到就返回-1
6、indexOf(String str,int fromIndex):从指定位置开始向后寻找,返回该字符串在指定位置后第一次出现的索引,返回值为int,如果没有找到就返回-1
String类型转换
1、getBytes():将字符串转为byte数组,返回一个byte数组
byte[] b = s.getBytes();
2、toCharArray():将当前字符串转为字符数组,返回一个字符数组
char[] b = s.toCharArray();
3、toUpperCase():将字符串中的英文全部提升为大写,返回一个新字符串(不在原有数据上发生改变)
4、toLowerCase():将字符串中的英文全部转为小写,返回一个新字符串
5、concat(String s):字符串的拼接,将指定的字符串和参数字符串进行拼接,用的比较少,因为+也能完成
6、系列方法valueOf():静态方法,可以将任意数据类型转为字符串类型,但是用的比较少,因为一般使用的时候 其他类型+""也可以完成
String str1 = String.valueOf(b);
增强for循环
增强for循环
增强for循环是for的一种新用法!用来循环遍历数组和集合。
增强for的语法
for(元素类型 e : 数组或集合对象) {
}
例如:
int[] arr = {1,2,3};
for(int i : arr) {
System.out.println(i);
}
泛型
1、泛型:广泛的类型,在定义一个类的时候,类中有一些方法参数,返回值不确定,就可以使用一个符号,来表示那些尚未确定的类型,这个符号就是泛型
2、对于有泛型的类,在这些类型的后面跟上尖括号,尖括号里写上具体的类型,作用就是确定类中声明的泛型在使用时的类型,(在使用某个类创建对象的时候,已经可以确定这个具体的类型,写出具体的)
3、泛型的好处:
在集合中如果定义了泛型,就表示该集合内,只能存储泛型类型的元素
提高了数据的安全性,将运行时期的问题,提前暴露在编译时期
避免了强转的麻烦
4、注意事项:
前后一致:在创建对象的时候,泛型符号前面和后面的泛型必须一致
泛型推断:java7的特性,如果前面的泛型括号内,已经写好了泛型,后面创建的对象的类型就可以只写一个尖括号,内容可以不写,<>菱形泛型/钻石语法
*保证了集合的安全性
泛型类
1、泛型类:带着泛型定义的类
2、格式:
class 类名<泛型类型1,泛型类型2,泛型类型3…>{
}
3、说明:
类名后面跟着的类型,是泛型的声明,一旦泛型声明出来,就相当于这个类型成为了一格已知类型,这个类型就可以在整个类中使用
泛型的声明名称:只要是一个合法的标识符即可,但是通常使用单个大写字母表示:常用的有T(type),V(value),K(Key),E(element)
泛型确定的时机,将来使用这个类的时候创建对象的同时确定
泛型方法
1、在方法声明上,带着泛型声明的方法,就是泛型方法
2、格式:
修饰符<泛型声明1,泛型声明2,泛型声明…> 返回值类型 方法名称(参数列表){
}
3、说明:
在方法上声明的泛型,可以在整个方法中当做已知类型来使用
如果使用非静态的方法没有任何泛型的声明,此时可以使用类中声明的泛型
如果是静态的方法,没有任何泛型的声明,此时就不可以使用泛型,类中也不能用,因为类中的泛型需要在创建对象的时候才能确定,所以静态方法,想要使用泛型,就必须在自己的方法上单独声明
*方法中声明的泛型需要在调用方法的时候,通过实际参数来确定泛型的类型
*所有的泛型,都是引用数据类型,基本数据类型还是不可以使用
import java.util.ArrayList;
import java.util.List;
public class Fanxing<K,V> {//泛型类
List l = new ArrayList<>();
public void add(V v){//泛型方法
l.add(v);
}
public void remove(V v){
l.remove(v);
}
public void print(V v){
System.out.println(v);
}
public void look(){
System.out.println(l);
}
}
public static void main(String[] args) {
Fanxing<Integer,Object> f = new Fanxing();
f.add(1);
f.add(2);
f.add(3);
f.add(4);
f.add(5);
f.look();
f.print(4);
f.remove(3);
f.look();
}
输出结果
若泛型类是某个成员类Person,则:
public static void main(String[] args) {
Fanxing<Integer, Person> f2 = new Fanxing<>();
f2.add(new Person("张三",20));
f2.add(new Person("李四",15));
f2.add(new Person("王五",25));
f2.look();
}
public class Person {
private String name;
private int age;
public void show(){
System.out.println("姓名:"+name+"\n"+"年龄:"+age);
}
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
泛型通配符
1、使用泛型的时候,没有具体的泛型声明,而是使用了和声明过的泛型T有关的一种类型,就称为泛型通配符
2、三种形式:
<?>:表示任意类型
<?extends T>:表示T或者T的子类
<?super T>:表示T或者T的父类
冒泡排序
以int[] a={5,4,3,2,1}为例(这里称i的循环为大循环,j的循环为小循环)
1、第一轮小循环后,数组变为{4,5,3,2,1},可以看出是a[0]和a[1]比较大小后,因为a[0>a[1]],所以交换了位置。交换位置后,由a[1]与a[2]进行比较,a[1]>a[2],于是再次交换位置,通过各种交换,完成了第一轮的大循环。
2、第一轮大循环后,数组变为{4,3,2,1,5},整体上可以理解为通过相邻位比较,寻找出最大值并赋值到最后一位。
3、第二轮大循环后,(由于i=1,所以小循环中j<a.length-1,在本例中为j<4,小循环次数变少),数组变为{3,2,1,4,5}。
4、第三轮大循环后,数组变为{2,1,3,4,5}
5、第四轮大汛后,数组变为{1,2,3,4,5},结束冒泡排序。
//冒泡排序,升序
public void order(int[] a){
for (int i = 0; i < a.length; i++) {
//每一轮循环都会确定第a.length-i位的数
for (int j = 1; j < a.length-i; j++) {
if (a[j-1]>a[j]){
//将相邻两位比较大小,如果前者大则交换位置
int b;
b = a[j-1];
a[j-1]=a[j];
a[j]=b;
}
}
}
}
this和super的用法
1、含义:
(1)this表示本类当前对象
(2)super表示本类当前对象父类部分的引用,哪个对象调用super所在的方法,super就代表哪个对象父类部分的数据
2、super和this都可以访问成员变量
(1)super只能访问父类中的成员变量
(2)this既可以访问父类中的成员变量,也可以访问子类中的成员变量
3、this和super都可以访问成员方法
(1)this既可以访问父类中的成员方法,也可以访问子类的
(2)super只能访问父类中的成员方法,格式 super.成员方法名(实际参数)
4、this和super都可以在构造方法中使用,但是使用的特点不同,可以用来访问构造方法的内容,this访问叫做this语句,super访问叫做super语句
(1)this(实际参数);访问子类的构造方法
(2)super(实际参数):访问父类的构造方法
(3)this()语句和super()语句,只能出现在构造方法的第一行,其他位置均不可以。
重载和重写的区别
1、如果父类和子类的方法名相同,但是实现不同,java把这个叫做方法的重写
(1)重载:在同一个类中,方法名相同,参数列表不同,与返回值类型无关
(2)重写:在父子类这种,方法名一样,参数列表一致,返回值类型一致,实现体不同
(3)java中通过@Override 检测一个方法是否是重写父类的方法
2、重写的方法本身还是属于父类的,只不过在子类中重新实现了这个方法的方法体
3、重写的注意的事项:
(1)私有的方法不能被重写
(2)方法在重写的时候,权限不能越来越小,子类应该是越来越强大的,功能应该越来越多,如果被私有了,此时子类就不会继承这个私有的方法,相当于到此为止,后续都没有这个功能,不能将父类中的内容重写没了。
静态常量
静态常量可以被改变,但如果加上final关键词,则静态常量不会再改变。
final关键字
用final修饰后表示不能再改变了
修饰类:表示一个类是最终的,此时不能有子类
修饰方法:表示这个方法不能被重写了,是一个最终方法
修饰变量:变量会变成常量,只能赋值一次,定义和赋值可以分开
修饰对象:表示这个对象不可改变,即地址不可改变
抽象类和抽象方法
1、抽象类定义:public abstract class 类名
2、抽象方法定义:public abstract 返回值类型 方法名称(参数列表);
只有方法的声明,没有方法的实现,这样的方法叫做抽象方法。
为了区分抽象方法和普通方法,需要在修饰符后面加上一个abstract
例如:public abstract void eat();
*抽象方法必须存在抽象类中
*抽象类中可以有静态成员和静态方法
3、抽象类和抽象方法的关系:抽象类中不一定有抽象方法,抽象方法必须在抽象类中
java中的常用Math方法
abs(数值类型):返回该类型的绝对值
ceil(double d):返回d的向上取整
floor(double d):返回d的向下取整
max(int a,int b):返回两个数的最大值
min(int a,int b):返回两个数的最小值
pow(double a,double b):返回a的b次幂 a²即 pow(a,2)
random():返回0~1.0的随机数,含0不含1 [0,1)
round():四舍五入
常用时间类
currentTimeMilles():返回当前时间的毫秒值,表示的是从历元时间1970年1月1日0时0分0秒到此时此刻的毫秒值,返回值类型是long类型,可以用于计算代码前后所花费的时间。
Date
1、Date表示特定的瞬间,精确到毫秒,是java中提供时间日期数据的对象
2、Date类的构造方法:
Date():创建Date对象,以分配时间(精确到毫秒值)
Date(long date):根据参数描述的时间,表示从历元时间过了date毫秒
3、常用方法:
getTime();相当于获取Date内封装的时间
setTime(long time);将时间修改为历元过了time毫秒的时间,直接设置新的时间
Date d = new Date();//创建date对象
long l1 = d.getTime();//当前时间
d.setTime(100000000);//设置新的时间
long l2 = d.getTime();//获取新的时间
System.out.println(l1);
System.out.println(l2);
SimpleDateFormat时间格式类
1、简单的日期格式化类,提供了日期的格式化方法,不具备任何时间,只能是格式,根据某些时间,按照指定的格式显示
2、SimpleDateFormat常用的构造方法
SimpleDateFormat():用默认的格式和默认语言环境的日期格式创建对象
SimpleDateFormat(String pattern):用给定的格式和默认语言环境创建对象,一般参数会传递yy-MM-dd HH:mm:ss
Date d = new Date();//创建date对象并获取当前日期
String sdf1 = "yyyy年-MM月-dd日 HH时:mm分:ss秒";//确定日期格式
SimpleDateFormat sdf = new SimpleDateFormat(sdf1);//根据新的日期格式创建对象
String s = sdf.format(d);//将当前时间转换为新的日期格式
System.out.println(s);//输出结果
Date d1 = sdf.parse("2022年-01月-01日 00时:00分:00秒");//获取第一个时间
long l1 = d1.getTime();//将date类型转为long类型
Date d2 = sdf.parse("2000年-01月-01日 00时:00分:00秒");//获取第二个时间
long l2 = d2.getTime();//将date类型转为long类型
System.out.println(l1-l2);//计算两个时间差值并输出
在上述代码中,日期格式的字符串sdf1也可以灵活更改,比如:
Date d = new Date();
String sdf1 = "yyyy年-MM月-dd日";
SimpleDateFormat sdf = new SimpleDateFormat(sdf1);
String s = sdf.format(d);
System.out.println(s);
Date d1 = sdf.parse("2022年-01月-01日");//获取第一个时间
long l1 = d1.getTime();//将date类型转为long类型
Date d2 = sdf.parse("2000年-01月-01日");//获取第二个时间
long l2 = d2.getTime();//将date类型转为long类型
System.out.println(l1-l2);//计算两个时间差值并输出
3、常用方法:
format(Date date):将一个Date格式化为日期字符串, 返回一个字符串(一般是新建一个日期格式sdf,通过sdf.format(Date d)来将d转为对应的格式)
parse(String sourse):给定时间字符串,按照指定的格式解析为时间对象 返回值为Date
IDEA常用快捷键
持续更新中…
快捷键 | 功能 |
---|---|
alt+insert | 补全构造函数、get和set方法、重构toString等 |
ctrl+D | 复制当前行 |
ctrl+shift+up/down | 代码块(行)在大括号内上/下移动 |
ctrl+/ | 单行注释(//) |
ctrl+shift+/ | 多行注释(/**/) |
ctrl+回车 | 代码补全,导入类、包等也可用 |
ctrl+alt+M | 提炼方法(实际使用时快捷键冲突,右键->Refactor->Extract Method同样可以) |
ctrl+alt+T | 快速将一段代码放入条件语句,try…catch,或循环语句中 |
ctrl+alt+l | 格式化代码(整理格式) |
ctrl+D | 向下复制代码 |
便捷代码 | 功能 |
---|---|
psvm/main | 快速敲出主方法 |
/**后按ctrl+回车 | 快速注释,一般用于方法前 |
a.sout | 快速输出a,相当于System.out.println(a); |
a.fori,a是个数组 | for (int i = 0; i < a.length; i++) |
a.for,a是个数组 | 增强for循环 , for (int i : a) |