java面向对象高级(根据青空的霞光总结)
# 面向对象高级(青空)
基本类型包装类
前置:
- 虽然java是面向对象的语言,但是基本类型不是面向对象的,如果想要让基本类型也能像面向对象的形式进行表达,就可以是用包装类
- 包装类实际上就是将我们的基本数据类型,封装成一个类(运用了封装的思想)
类型:
- byte -> Byte
- boolean -> Boolean
- short -> Short
- char -> Character
- int -> Integer
- long -> Long
- float -> Float
- double -> Double
装箱拆箱
-
使用包装类会自动装箱与拆箱,也就是可以直接将一个基本类型的值赋值给一个包装类,编译器自动将这个基本类型进行了装箱。
-
Integer i = 11; //与 Integer i = new Integer(11)一致 或者 Integer i = Integer.valueOf(10) 把一个基本类型转为包装类 int a=i.intValue(); //与 int a=i.intValue() 一致; intvalue() :将一个包装类转化为int这种基本类型
imagecache
-
要判断两个数字是否相等,
-
如果是基本类型,就可以直接使用==
-
如果是包装类的对象,直接使用==是判断是否是同一个对象
-
但是如果使用自动装箱,这里的得到的依然是true 因为自动装箱机制(valueof)中有一个imagecacche这样一个缓存机制,他会缓存-127到127的所有数到一个数组中,进行自动装箱创建对象就会从缓存中拿到那个对象,始终只能拿到一个对象,所以==就是true,equal也是一样,如果超出了-127到127就也是false
-
Integer i=10; Integer a=10; System.out.println(i==a);
-
如果直接声明两个integer对象,再使用==判断,就是false了
-
这时要判断对象的值是否相等就要使用equal来判断
-
Integer i = new Integer(10); Integer a = new Integer( 10); System.out.println(i.equals(a));
-
-
包装类的方法
-
字符串转换成int(int转字符串 )
-
Integer i = new Integer(10); String str=String.valueOf(i); System.out.println(str); String str="123"; Integer i=Integer.valueOf(str); // Integer i=Integer.parseInt(str); System.out.println(i);
-
-
对十六进制与八进制进行编码
-
转10进制
-
Integer i=Integer.decode("0x10"); System.out.println(i);
-
十进制转其他进制:
-
System.out.println(Integer.toHexString(12)); /16进制
-
-
-
对象的值是否相等
特殊包装类
void
void也有包装类,但是只能等于null,没啥用
BigInterger
计算一个很大的数字
-
如果使用基本类型,当数据超出范围就会出错。
-
BigInteger i = BigInteger.valueOf(Long.MAX_VALUE); //放入long能表示的最大数 System.out.println(i);
-
计算方式 :不能使用运算符,而是使用特定的方法进行 ,而且得到的结果以返回值得形式存在,需要另一个biginteger来接收
-
BigInteger i = BigInteger.valueOf(Long.MAX_VALUE); //放入long能表示的最大数 BigInteger a=i.add(BigInteger.valueOf(Long.MAX_VALUE) ); //加法 System.out.println(i);
-
BigInteger i = BigInteger.valueOf(Long.MAX_VALUE); //放入long能表示的最大数 BigInteger a=i.multiply(BigInteger.valueOf(Long.MAX_VALUE) ); //乘法 System.out.println(a);
-
精确计算小数
BigDecimal i= BigDecimal.valueOf(10);
BigDecimal a=i.divide(BigDecimal.valueOf(3),100,BigDecimal.ROUND_FLOOR); //第一个参数是要除的值,第二个是小数位数(对于无限循环小数),第三个是第一百位数字的保留形式 (向下取整)
System.out.println(a);
数组
可变长度的数组
- 因为方法是可以有不确定个数的参数,这些参数,都是使用数组来保存的
字符串
由于java中没有字符串这种基本数据类型,所以要实现字符串,就要使用类
String 类
- String本身也是一个类,只不过它比较特殊,每个用双引号括起来的字符串,都是String类型的一个实例对象
- 创建:
- 可以直接双引号,如果是直接使用双引号创建的字符串,如果内容相同,为了优化效率,那么始终都是同一个对象
- 可以new一个对象,值放到括号里,new出来的就不是一个对象了
- 判断是否内容相同使用equal
一些方法
-
str.length 返回字符串长度
-
str.substring(开始下标,结束下标) 分割字符串,并返回一个新的子串对象 与Python的切片一样
-
str.split(“分割的标志”) 通过给定的标志字符来分割字符串,如 a.b.c.d 若按照点来切割,就得到【a b c d】 这样一个数组
-
字符数组和字符串之间是可以快速进行相互转换的
-
char[] a={'1','2','3'}; String i= new String(a); System.out.println(i);
-
String i="123"; char[] a=i.toCharArray(); System.out.println(a);
-
StringBuilder
使用StringBuilder来连接字符串
我们可以通过+来连接字符串,在编译时,会自动将这两个字符串连接后赋值给一个String对象,如果+很多,就要一个一个加,中间就会产生多个中间String对象,就比较浪费资源,直接使用StringBuilder来连接就好很多
使用
String i="123";
String str="ni";
String str1="干";
String str2="嘛";
StringBuilder sb=new StringBuilder();
sb.append(i).append(str).append(str1).append(str2);
System.out.println(sb.toString());
正则表达式
想要判断用户输入的内容是否满足某种格式(如邮箱格式),如果满足返回true,不满足返回false
比较的函数
- java的字符串中提供了matches这个方法,用正则来匹配
内部类
成员内部类
内部类:就是在类的内部再定义一个类
使用
-
public class cls { public class Test{ public String name; public void getMessage(){ System.out.println("这是一个内部类"); } } }
-
public class main { public static void main(String[] args) { cls cls = new cls(); cls.Test test=cls.new Test(); test.getMessage(); } }
-
内部类可以访问外部类的属性与方法,但外部类不能访问内部类
-
对于同名变量的调用
-
public class cls { public String name; public class Test{ public String name; public void getMessage(String name){ System.out.println(name); System.out.println("第二个name "+this.name); System.out.println("第三个name "+cls.this.name); System.out.println("这是一个内部类"); } } }
-
public class main { public static void main(String[] args) { cls cls = new cls(); cls.Test test=cls.new Test(); test.getMessage("第一个name "); } }
-
对于super的使用也是一样的
-
静态内部类
就是在成员内部前加上static关键词使其变成静态
使用
-
public class Cls { public String name; public static class inner{ public void getmessage(){ System.out.println("这是一个静态内部类"); } } }
-
public class main { public static void main(String[] args) { Cls.inner inner=new Cls.inner(); //不需要依托与对象了 inner.getmessage(); } }
-
因为内部类是静态的所以无法访问外部,除非外部也是一个静态的属性或者方法
局部内部类
声明在类中的方法中的类
public class Cls {
public String name;
public static String x="这是x";
public void getmessage(){
class inner{ //不允许使用修饰符
}
inner inner = new inner();
}
}
匿名内部类
作用
抽象类和接口的方法的实现:1.子类继承,子类实现,2.使用匿名内部类
使用
public class Main {
public static void main(String[] args) {
Student student=new Student() { //new 的时候加上花括号,把抽象方法实现一下,并创建创建出实例对象
@Override
public void getmessage() {
System.out.println("这是一个匿名内部类");
}
};
student.getmessage(); //这里的student就是已经实现了抽象方法的一个实例对象,但是这个类甚至没有名字,就直接有了一个实例对象
}
}
public interface Student {
public void getmessage();
}
- 抽象类也可以。
- 普通类也可以创建匿名内部类,但是意义不大。
lambda表达式
作用:
- 可以认为其实就是匿名内部类的简写(底层其实不是简简单单的替换)
条件
- 必须是只有一个必须要实现的匿名方法的接口。它不支持抽象类,因为抽象类不是只有方法,它还有属性
- 假如接口中有两个抽象方法,其中一个使用了default 有默认实现,也行
格式
-
标准格式为:
([参数类型 参数名称,]...) ‐> { 代码语句,包括返回值 }
-
无参数或参数为多个时括号必须写,只有一个参数可以省略括号,类型也可以省略
-
代码语句只有一句,花括号可以省略,
-
代码语句只有返回值语句,return和花括号都可以省
-
那么就会出现这样的语句
-
public class Main { public static void main(String[] args) { Student student= a-> a; 参数先省去括号和类型,只有返回值语句,省略return和花括号 System.out.println(student.getmessage(33)); } }
public interface Student { public int getmessage(int a); }
-
使用
- 使用前
public class Main {
public static void main(String[] args) {
Student student=new Student() {
@Override
public void getmessage() {
System.out.println("这是一个匿名内部类");
}
};
student.getmessage();
}
}
-
使用后
-
public class Main { public static void main(String[] args) { Student student= () -> System.out.println("这是一个匿名内部类"); student.getmessage(); } }
-
如果某个方法的参数是一个接口的实现,那么就可以使用这个
-
public class Main { public static void main(String[] args) { Student student= a-> a; System.out.println(student.getmessage(33)); get(student); } public static void get(Student student){ System.out.println("啊,确实挺不错的"); } }
-
方法引用
概念
- 直接将已经实现了的现成方法(自己实现的,或者jdk已经实现好的)拿过来当做抽象方法的实现。
- 当然方法的名称,参数,返回值等等都需要一致
使用
-
比如有一个接口中只有一个相加的方法
-
public interface Student { public int sum(int a,int b); }
-
-
使用匿名内部类 和lambda都可以实现
-
public class Main { public static void main(String[] args) { Student student=(int a,int b)->a+b; System.out.println(student.sum(1,3)); } }
-
-
但是还可以更简单,因为sum这个方法,在integer中已经有过定义了,我们就可以直接把他引用过来
-
public class Main { public static void main(String[] args) { Student student=Integer::sum; System.out.println(student.sum(1,3)); } }
-
-
再比如有这样一个接口,并没有一个现成的类实现了该方法
-
public interface Student { public void getmessage(); }
-
-
我们就可以自己实现出来,把自己的方法引用上,我觉得一般是用的时候恰好,在之前我们已经实现过了这个方法,我们直接引用了该方法
-
public class Main { public static void main(String[] args) { Main main = new Main(); Student student=main::getmessage; student.getmessage(); } public void getmessage(){ System.out.println("这是一个被方法引用的方法"); } }
-
异常处理
分类
- 运行时异常
- 继承自runtimeexception
- 编译时异常
- 继承自exception
- 错误 error
- 直接导致jvm运行不了了
- RuntimeException继承自Exception,Exception继承自Throwable
抛出异常
-
当别人给出了错误的参数,使程序无法运行,就可以手动抛出运行时时异常,使程序终止
-
public class Except { public static void main(String[] args) { div(1,0); } public static int div(int a ,int b){ if(b==0){ throw new ArithmeticException("除数不能为零"); } return a/b; } }
-
程序终止并打印出栈信息
- Exception in thread "main" java.lang.ArithmeticException: 除数不能为零
at com.ximenheiniu.blog.except.Except.div(Except.java:10)
at com.ximenheiniu.blog.except.Except.main(Except.java:5)
- Exception in thread "main" java.lang.ArithmeticException: 除数不能为零
-
如果我们在方法中抛出了一个非运行时异常,那么我们就要告知函数的调用方,我们抛出了一个异常,调用方要进行处理
-
public class Except { public static void main(String[] args) throws Exception{ div(1,0); } public static int div(int a ,int b) throws Exception{ throw new Exception("出错啦"); } }
-
-
如果不同分支会造成不同异常,就都要抛出
-
运行时异常也可以抛出,但是不做要求
-
异常的处理
为啥要处理
- 程序在遇到异常后会终止程序,但是我们希望程序遇到异常后可以跳过异常运行完。
处理方式
-
我们可以将可能会出错的代码写到try语句中,catch语句写发生异常后运行的代码
-
注意:catch中捕获的类型只能是Throwable的子类,,也就是说要么是抛出的异常,要么是错误,不能是其他的任何类型。
-
如果某个方法明确指出会抛出异常,而且是非运行时异常,我们一定要处理,否则无法编译
-
当然我们也可以不在这一级处理该异常,而是将异常抛出,让上一级去处理
-
如果我们要捕获的异常,是某个异常的父类,那么当发生这个异常时,同样可以捕获,有点像是用异常的父类来泛指了一下子类异常
-
catch可以有多个,当代码可能发生多种异常,不确定是哪一个,就可以多个catch,但是注意子类在前,父类在后,否则子类永远不会被捕获,最后要有一个exception兜底
-
也可以一个catch,异常用括号括起来,中间用 | 隔开。
-
try{ }catch (ArithmeticException){ }catch (Exception){ }
-
try{ }catch (NullPointerException | IndexOutOfBoundsException e){ };
-
-
-
当我们希望,程序运行时,无论是否出现异常,都会在最后执行任务,可以交给
finally
语句块来处理
常用工具类
数学工具类
这个类是java.util
包下类
- 乘方
- Math.pow(5,7) 5的7次方
- 绝对值
- Math.abs(-1)
- Math.max 最大值
- 算数平方根
- Math.sqrt()
- Math.PI
- Math.E
- Math.sin
- Math.log
- Math.ceil 向上取整
- Math.floor 向下取整
- Random rand=new Random(); random.nextint(100); 生成随机数
数组工具类
这个类也是java.util
包下类
-
打印:arrays.tostring()
-
排序:arrays.sort(arr)
-
填充 : arrays.fill(arr,填充物)
-
复制:
-
import java.util.Arrays; public class Except { public static void main(String[] args) throws Exception{ int[] a={1,23,4,65,213,564,6}; int [] x=Arrays.copyOf(a,12); //复制a数组生成一个新的数组,并给出数组的长度 System.out.println(Arrays.toString(a)); System.out.println(x.length); } }
-
public class Except { public static void main(String[] args) throws Exception{ int[] a={1,23,4,65,213,564,6}; int [] x=new int[10]; System.arraycopy(a,1,x,2,5); //(源数组,源数组复制起始位置,目标数组,,目标数组放置起始位置,复制长度) 利用数组进行搬运 System.out.println(Arrays.toString(x)) } }
-
import java.util.Arrays; public class Except { public static void main(String[] args) throws Exception{ int[] a={1,23,4,65,213,564,6}; int []x=Arrays.copyOfRange(a,0,1); //选择范围进行复制 System.out.println(Arrays.toString(x)); } }
-
-
查找
-
对于有序数组可以使用二分查找
-
public class Except { public static void main(String[] args) throws Exception{ int[] a={1,23,4,65,213,564,6}; Arrays.sort(a); System.out.println(Arrays.binarySearch(a,1)); } }
-
-
-
判断相等
-
public class Except { public static void main(String[] args) throws Exception{ int[][] a = new int[][]{{2, 8, 4, 1}, {9, 2, 0, 3}}; int[][] b = new int[][]{{2, 8, 4, 1}, {9, 2, 0, 3}}; System.out.println(Arrays.equals(a, b)); //equals仅适用于一维数组 System.out.println(Arrays.deepEquals(a, b)); //对于多维数组,需要使用deepEquals来进行深层次判断 } }
-
练习
冒泡排序
-
有一个int数组,但是数组内的数据是打乱的,现在我们需要将数组中的数据按从小到大的顺序进行排列:
-
import java.util.Arrays; public class MaoPao { public static void main(String[] args) { int[] arr = new int[]{3, 5, 7, 2, 9, 0, 6, 1, 8, 4}; int [] a=sort(arr); System.out.println(Arrays.toString(a)); } public static int[] sort(int[] arr ){ int tmp=arr[0]; for (int j = 0; j < arr.length-1; j++) { for (int i = 0; i <arr.length-1-j; i++) { if(arr[i]<arr[i+1]){ tmp=arr[i]; arr[i]=arr[i+1]; arr[i+1]=tmp; } } } return arr; } }
二分查找
public class Binarysearch {
public static void main(String[] args) {
int[] arr = {1, 3, 4, 6, 7, 8, 10, 11, 13, 15};
int target = 1;
int result = binarysearch(arr, target);
System.out.println(result);
}
public static int binarysearch(int[] arr, int target) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (arr[mid] > target) {
//mid以及mid以后的就不用找了
right = mid - 1;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
return mid;
}
}
return -1;
}
}
斐波那契(青蛙跳台阶)
//斐波那契
public class Frog {
public static void main(String[] args) {
int result=jump(2);
System.out.println(result);
}
public static int jump(int n){
int [] arr=new int[n+1];
//考虑到如果n是0,就也是一种
arr[0]=1;
arr[1]=1;
for (int i = 2; i <=n ; i++) {
arr[i]=arr[i-1]+arr[i-2];
}
return arr[n];
}
}