Java基础
封装(通过private对类中属性进行隐藏,通过get、set方法来获取或赋值)
可以提高程序的安全性,保护数据 在方法中可以隐藏代码的实现细节 统一接口、统一规范 增加系统可维护性 继承(关键字extends。java中所有类都直接或间接的继承了Object类)
子类继承了父类,就会拥有父类所有的方法和属性(除了修饰符是static和private的)(父类属性是私有的private的话,子类无法获取,需要通过get、set) java中只有单继承,没有多继承(一个儿子只能有一个父亲,一个父亲能有多个儿子) 子类调用父类属性或方法可以使用super,但是父类私有private私有东西子类无法调用 子类继承父类,new一个子类的时候,会先调用父类的构造器,子类构造器会有隐藏代码super();如果想显现写出来super();必须放在子类构造器第一行 多态(同一方法会根据对象的不同,而采取不同的行为方式)
多态是方法的多态,属性没有多态 父类和子类,要有联系,否则类转换异常(ClassCastException(类转换异常)) 存在条件:
有继承关系 方法需要重写 父类引用指向子类对象 Father f = new Son(); 重写(需要有继承关系,子类重写父类的方法)
重写都是方法的重写,和属性无关 两个方法名必须相同,参数列表也必须相同 两个方法体不一样 如果方法是static、final、private修饰,则无法被重写 A extends B 如果方法是static静态方法,那么方法的调用只和左边定义的数据类型有关B b = new A();调用的会是B类中的方法 A extends B 如果方法是非静态方法,B b = new A();相当于子类A重写了父类的方法,调用的会是A类中的方法 子类继承父类,并且和父类方法名字相同,只不过方法的实现不一样,叫做重写,并且方法修饰符必须是public 为什么要用重写? 当父类方法不满足子类,或者子类不一定需要,就需要重写来实现子类自己想需要的东西 扩展
子类重写父类的方法,修饰符可以扩大但不能缩写 private < default < protected < public 相反,抛出的异常,范围可以缩小,不能放大 重载
方法重载:在同一个类中,有相同的方法(函数)名,但是形参不同的函数 方法名称必须相同 参数列表必须不同(参数个数不同,参数类型不同,参数排列顺序不同) 方法的返回类型可以相同,也可以不相同, 仅仅返回类型不同,不足以是方法的重载 Super
super调用父类的构造方法,必须super();放在构造方法的第一行 super只能出现在子类的方法或者构造方法中 super和this不能同时调用构造方法(谁都得放第一行就会报错) instanceof
x instanceof y(判断x是不是属于y类型) 类型转换(方便方法的调用,减少重复的代码)
Father f = new Son();子类转成父类,低转高可直接转(向下转型) Son s = (Son) new Father();父类转成子类,高转低需要强制转换(向上转型) static
被static修饰过的方法或者属性,可以通过ClassName.param;或者ClassName.method();来直接调用 不仅可以用在属性或者方法上,还可以放到import导入包中(import static java…) 当一个类中同时有static代码块、匿名代码块、无参构造方法代码块(new Class()对象的时候执行顺序为:static > 匿名 > 无参构造方法)
static: static{System.out.println(“静态代码块”);} 匿名代码块: {System.out.println(“匿名代码块”);} 构造方法: public ClassName(){System.out.println(“构造方法代码块”);} static是和类一块加载,所以优先执行static的方法,但是只会执行一次,后面再实例化对象不会出发static中的方法 final
final修饰过的类不能被继承 final修饰过的方法不能被重写 final修饰的属性必须有初始化值,并且不可以修改 抽象类(abstract 约束~)
抽象类中方法靠其他类extends来实现抽象方法,只能单继承 抽象类不可以被new 抽象方法没有方法体,只有名字和类型 抽象类中可以写普通的方法 抽象方法必须在抽象类中 接口(interface)
定义
接口中方法都是public abstract进行修饰(可以省略不写,只写返回类型、方法名称、参数即可) 接口中属性都是public static final进行修饰(可以省略不写,定义后就是常量,不可修改) 接口和抽象类都不能被实例化,他们根本没有构造方法 类可以实现多个接口,多继承关系 implement xService,yService,zService… 类实现接口必须要重写里面接口中所有定义的方法 作用
约束规范 定义一些方法,由他人实现 解耦可复用,后期维护更方便 异常体系结构(Throwable) Throwable(分为Error和Exception)
Error
由java虚拟机jvm生成并抛出,大多数遇到Error与开发代码无关,如内存溢出 Error通常是灾难性的致命错误,是程序无法控制和处理的,当出现这种异常时,java虚拟机jvm一般会终止线程 Exception(分为运行时异常和非运行时异常)通常情况下是可以被程序处理的,并且程序中要尽可能的去处理这些异常
RuntimeException(运行时异常)
ArrayIndexOutOfBoundsException(数组下标越界异常) NullPointerException(空指针异常) ArithmeticException(算术异常) MissingResourceException(丢失资源异常) ClassNotFoundException(找不到类异常) … 非运行时异常
处理异常(Ctrl + Alt + T 快捷键生成try catch代码块)
try(监控代码区域) catch(捕获代码) finally(善后工作,不管有无异常,都会执行) throw(主动抛出异常,一般用作方法体中 throw new Exception) throws(如果方法体处理不了异常,使用throws抛出异常放到方法上,让调用方去处理 void add() throws Exception{}) 自定义异常
自定义异常MyException需要继承父类总异常 MyException extends Exception 需要toString方法输出自定义异常信息public String toString() { return “MyException:{num接受的值不可以为0!}”; } 方法可能会出现自定义异常,可以做以下处理
1:方法只做出抛出异常throws MyException处理,调用方需要自行try catch进行捕获 2:方法内部自己try catch捕获异常,调用方不做处理,可直接调用方法 数据类型(分为基本数据类型和引用数据类型)
基本数据类型
byte、short、int、char、long、float、double、boolean 引用数据类型
数据类型之间转换
低容量到高容量升序(byte->short->char->int->long->float->double) int i = 128; byte b = (byte) i;(高到低需要强制转换 (类型)变量名 会输出-128) double d = i;(低到高自动转换 会输出128.0) 类型转换注意
1:不能对布尔值进行转换 2:不能把对象转成不相干的类型 3:高容量转低容量的时候,需要强制转换 4:转换的时候可能存在内存溢出,以及精度问题 变量
声明变量
byte num3 = 1; short num2 = 1; int num1 = 1; long num4 = 1L; float num5 = 1F;//小数:浮点数 double num6 = 1D; char c = ‘b’;//字符 boolean flag = true;//布尔:否 boolean flag1 = false;//布尔:否 int money = 10_0000_0000;//jdk7特性,数字之间可以用下划线分割,方便看数 String name = “xx”;//声明单个变量 String name1 = “xx”, name2 = “xx”;//声明多个变量 int a = 1, aa = 2; 局部变量和实例变量
局部变量必须声明和初始化值 (一个class中有个方法,方法中有个属性,即局部变量) 实例变量中如果值未被初始化,这个值默认是0或者0.0 或者null,注意:布尔值默认是false;(在class下有个变量,即实例变量) 常量
final static type varName = “a”; static final type varName = 1; 常量也必须声明和初始化,修饰符顺序无关,全局使用中不可修改 命名规范
所有变量、类、方法都要:见名知意 类成员变量、局部变量、方法名 要遵循驼峰命名 man goodMan 常量要大写,多词组用下划线分割 final static int NAME_LENGTH = 10; 类名 首字母要大写,并且遵循驼峰命名 Man GoodMan; 可变参数(通过…声明多个相同类型的变量,多个参数出现…只能放到最后面)
public static void manyVariable(int… num){} 调用时
manyVariable(new int[]{1, 2, 3});//可以传输数组类型 manyVariable(3, 4);//也可以传多个相同类型的数字 通过cmd编译代码,并运行
使用cmd命令行需要先编译代码 javac xx.java 生成xx.class文件 如果class文件在包下面,需要到src层去执行代码()可以通过命令行来给main方法中args传参 命令 java com.xx.xx.xx.class -encoding UTF-8 -charset UTF-8 str1 str2 str3 调用main方法传参给args
Class.main(new String[]{“wo”,“ai”,“hwq”}); 运算符
1:算数运算(一元运算、二元运算)
{ + - * / % ++ --(++ --是自增1和自减-。x++是代码执行完这一行i才会+1,++x是代码运行到这一行x已经-1,-- 同理) } 2:赋值运算
3:关系运算
4:幂运算
幂运算,例如2^3,2的三次方,2³ = 2 * 2 * 2 = 8 很多时候,我们会使用工具类来进行数据操作System.out.println(Math.pow(2, 3)); 5:逻辑运算((&&)并且、 (||)或者、 (!)取反)
&& 两个都为真,结果才是真(判断到第一个比较是假,则直接返回假,也就是直接短路) || 两个有一个真,结果就是真(判断到第一个是真,则直接返回真) ! 如果是真,则为假,如果是假则为真(取反) 6:短路运算
当第一个条件不满足时,&&会直接返回false,后面的不做判断 7:扩展赋值运算(偷懒写法)
(+= -= *= /=)a+=b 同 a = a + b; 8:三目运算(条件运算&三元运算)
x ? y : z(如果x是true的话,结果为y,否则为z) 实例:int a = 10; String str = a < 12 ? “小于12” : “大于12”; (输出小于12) 9:字符串连接符
int a1 = 10,b1 = 20;
System.out.println(“”+a1+b1);//输出1020 String在前面,后面的开始拼接字符 System.out.println(a1+b1+“”);//输出30 String在最后面,前面的开始计算,不拼接 System.out.println(a1+“”+b1);//输出1020 String在中间,也是拼接 递归(可以用简单的程序来解决复杂的方法,大大减少了代码量,它的能力在于用有限的语句来定义对象无限的集合)
递归头:处理什么时候不调用自身方法,如果没有头,将会陷入死循环 递归体:什么时候需要调用自身方法 例子:计算阶乘(5! = 5 * 4 * 3 * 2 * 1)
public class Recursion {
public static int factorial ( int num) {
if ( num == 1 ) {
return 1 ;
} else {
return num * factorial ( num - 1 ) ;
}
}
public static void main ( String [ ] args) {
System . out. println ( factorial ( 5 ) ) ;
}
}
while和dowhile(while是先判断再执行,dowhile是先执行后判断,所以dowhile最少会执行一次)
//while
public static void testWhile() {
int i = 1;
int sum = 0;
while (i <= 100) {
sum += i;
i++;
}
System.out.println(sum);
}
//dowhile
public static void testDoWhile(){
int i = 0;
int sum = 0;
do {
sum+=i;
i++;
}while (i<=100);
System.out.println(sum);
}
数组[]
定义数组
int[] a = {1, 1, 1}; int[] c = new int[]{1, 2, 3}; //静态初始化(声明即赋值) int[] b = new int[5]; b[0] = 1; //动态初始化(包含默认初始化,int类型不赋值默认为0,String类型默认为null…) 数组特点
1:长度是确定的,数组一旦被创建,它的大小就不可以被改变了 2:元素必须是相同类型,统一的,不能出现其他元素类型 3:数组类型可以是任意数据类型,包括基本类型和引用类型 4:数组变量属于引用类型,数组也可以看成是对象,数组中的每个元素相当于对象中的成员变量 Java中对象是存在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的 Arrays工具类的简单使用
int[] a = {1,5,3,4,7,5,6,9}; System.out.println(Arrays.toString(a));//输出a数组 Arrays.sort(a);//给数组排序(升序) Arrays.fill(a,0);//给数组填充值(下面将所有数组中元素变成0) Arrays.fill(a,2,5,0);//指定元素下标起点和重点index填充0(前包后不包,下标为2,3,4的会变成0)
//冒泡排序
public static int[] bubbleSort(int[] array) {
//临时变量
int temp;
//外层循环,遍历每个元素
for (int i = 0; i < array.length - 1; i++) {
//内层循环,开始比较相邻元素,将最大值放到最前
for (int j = 0; j < array.length - 1 - i; j++) {
if (array[j + 1] > array[j]) {
//相比较后大的值先放到临时变量中
temp = array[j + 1];
//较小的值将放到j+1后一位元素中
array[j + 1] = array[j];
//最后较大的值放入j的位置,到此两个数比较大小后,位置也发生完变化
array[j] = temp;
}
}
}
return array;
}
//反转数组
static int[] nums = {1, 2, 4, 3};
public static void reverseNums() {
int[] reverseNums = new int[nums.length];
// 方法1
int k = 0;
for (int i = nums.length - 1; i >= 0; i--) {
reverseNums[k] = nums[i];
k++;
}
//方法2
for (int i = nums.length - 1, j = 0; i >= 0; i--, j++) {
reverseNums[j] = nums[i];
}
if (reverseNums.length != 0) {
System.out.print("反转数组后值为:");
for (int reverseNum : reverseNums) {
System.out.print(reverseNum + "\t");
}
}
}
//二维数组
public static void main(String[] args) {
//定义二维数组
int[][] twoDimensionArray = new int[1][5];
//赋值
twoDimensionArray[0][1] = 1;
twoDimensionArray[0][2] = 2;
//直接声明二维数组
int[][] twoDimensionArray1 = {{1, 2, 3}, {1, 2, 3}, {3}};
for (int i = 0; i < twoDimensionArray1.length; i++) {
System.out.print("\n");
System.out.print("二维数组中第" + i + "个中的元素值为:");
for (int j = 0; j < twoDimensionArray1[i].length; j++) {
System.out.print(twoDimensionArray1[i][j] + "\t");
}
}
}
构造器(public ClassName(){})
和类方法名相同
没有返回值 使用new关键字的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化值,以及对类中的构造器进行调用(有参无参数构造方法),这些调用完才会new出来对象 使用new关键字,本质就是在调用构造器,用来初始化值 一个class即使什么都不写,也会存在一个无参构造方法 作用:
注意点:
定义了有参构造的时候,如果想调用无参构造,那么类中必须定义一个无参构造方法,否则报错 for循环
for (int i = 0; i <= 100; i++){} break; 终止循环 continue; 跳出本次循环
//break; 终止循环,会输出到19,20 == 20 break会终止循环
for (int i = 0; i < 100; i++) {
System.out.println(i);
if (i == 20) {
break;
}
}
System.out.println("遇到20刺客,我们已经撤退!");
//continue; 跳出本次循环,会输出0-30能整除3的数
for (int j = 0; j < 30; j++) {
if(j%3==0){
System.out.println("能干干净净吃掉3的,咱也不要!");
continue;
}
System.out.println(j);
}
//死循环
for (; ; ) {
//计算0-100之间奇数和偶数的和
public static void zeroToOneHundredOddEvenSum() {
int oddSum = 0;
int evenSum = 0;
for (int i = 0; i <= 100; i++) {
//i余(模)2 = 0,代表偶数
if (i % 2 == 0) {
oddSum += i;
} else {
evenSum += i;
}
}
System.out.println("奇数和为:" + oddSum + "偶数和为:" + evenSum);
}
//找出0-1000能被5除的整数,并且每行输出三个
public static void zeroToKiloDivideFive() {
for (int i = 1; i <= 1000; i++) {
if (i % 5 == 0) {
System.out.print(i + "\t");
}
if (i % (5 * 3) == 0) {
System.out.println();
}
}
}
//99乘法表
public static void nineMultiplyNine() {
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(i + "*" + j + "=" + i * j + "\t");
}
System.out.println();
}
}
//打印三角形
public static void printTriangle() {
int n = 5; // 定义一个整型变量n,表示三角形的高度
for (int i = 1; i <= n; i++) { // 外层循环控制行数,从第一行开始到第n行结束
for (int j = 1; j <= n - i; j++) { // 内层循环控制每行的空格数,从第一行开始到第n-i行结束
System.out.print(" "); // 输出一个空格
}
for (int k = 1; k <= 2 * i - 1; k++) { // 内层循环控制每行的星号数,从第一行开始到第2*i-1行结束(1,3,5,7,9 规律2*i-)
System.out.print("❤"); // 输出一个星号
}
System.out.println(); // 换行,进入下一行的输出
}
}
//高阶语法使用
int[] num = {10, 20, 30, 40, 50};
for (int i : num) {
System.out.println(i);
}
值传递
在Java中,传递方式只有一种,那就是值传递。
当我们传递基本数据类型(如int、float、boolean等)时,会复制一个新的值。 如果我们在方法中修改了这个值,那么原始的值并不会改变。这就是值传递的基本概念。 而当我们传递对象引用时,虽然引用本身的值(即内存地址)并没有被改变,但是通过这个引用我们可以修改对象的状态。 这就是因为Java中的对象是通过引用传递的。换句话说,传递的是对象的引用,而不是对象本身。
/**
* 值传递
* 在Java中,基本数据类型(如int、float、double)是按值传递的,而不是按引用传递的。
* 当将一个变量的值传递给一个方法时,该方法会创建一个新的变量(在这个例子中是num),该变量的值与原始变量的值相同。
* 所以,在change方法中更改num的值时,只是更改了传递给方法的num的副本的值,而原始的num变量的值并没有改变。
*/
public class ValueTransmit {
public static void main(String[] args) {
int num = 1;
System.out.println(num);//输出1
change(num);
System.out.println(num);//输出1
String str = "en";
changeStr(str);
System.out.println(str);//输出en
}
public static void change(int num) {
num = 10;
}
public static void changeStr(String str){
str = "enen";
}
}
/**
* 引用传递:对象,本质还是值传递
*/
public class CiteTransmit {
public static void changeName(Person person){
//现在person是一个对象,指向的Person person = new Person();这是一个具体的人,所以可以改变属性值
person.name = "lxxxxx";
}
public static void main(String[] args) {
Person person = new Person();
person.name = "lx";
System.out.println(person.name);//输出lx
changeName(person);
System.out.println(person.name);//输出lxxxxx
}
}
class Person {
String name;
}