Java基础

Java基础

数据类型

java中有八种数据类型

  1. byte
  2. short
  3. int
  4. long
  5. float
  6. double
  7. String
  8. char

类型转换

数据类型的转换分为两种:强制转换和自动转换

自动转换:例如:int转换为double ,java中规定好的,由低到高的转换,不需要强制执行,java的源码中已经设定好。

强制转换:例如:

1
2
3
int a = 125;
byte b = byte(a);

如上,一个int类型的变量被强制转换为byte类型,这是由高到低,因此需要强制转换,即在被转换的变量前加转换后的数据类型。

注意:强制数据类型转换存在一个和严重的问题,即内存溢出

1
2
int a = 128;  // int
byte b = byte(a); // 会出错,原因是byte数据类型的最大值是127,存在内存溢出

变量、常量、作用域

变量:指的是在内存中的一个空间,可以放你想放的任何东西,由于不确定性所以取名变量。

常量:用final修饰的一个固定的值,其中变量的名字需要大写

作用域

  1. 类的作用域

    static 修饰类的全局作用域,不论是前置还是后置都一样。

  2. 实例变量作用域
    String name = “李四”;

  3. 方法的作用域

​ main方法里面定义的变量

自增和自减

a++:先自增,后赋值

++a:先赋值,后自增

逻辑运算、位运算

&& : 两个都为真,结果才是真

|| :有真即真

!:取反


<<

左移,乘以2

》》

右移,除以2

^

三元运算

1
2
double a = 80;
double b = a < 60 ? "及格":"不及格"

Sanner类

  1. 导入Scanner类
  2. new出Scanner
  3. 变量接受输入
  4. 关闭Scanner

next():以空格结束

hasnext():以Enter键结束

判断输入的数据类型方法:

hasNextInt():判断输入的数据是否是int类型

hasNextfloat():判断输入的数据是否是float类型

顺序结构

java的基本结构就是顺序结构,除非特别申明,否则一定是一行一行执行,同时顺序结构也是最简单的算法结构。

if选择结构

  • if单选择结构
1
2
3
4
5
if(布尔表达式){
//如果表达式为true,则执行
}else{
// 如果为false。则执行
}
  • if多选择结构
1
2
3
4
5
6
7
8
9
10
11
if(布尔表达式){
//如果表达式为true,则执行
}else if(布尔表达式1) {
//如果表达式1为true,则执行

}else if(布尔表达式2){
//如果表达式2为true,则执行

}else{
// 如果以上表达式结果均为false。则执行,若有一个表达式为true,则跳过else
}
  • 嵌套if
1
2
3
4
5
6
7
if(布尔表达式1){
//如果表达式1为true则进入表达式2
if(布尔表达式2){
//如果表达式2为true则执行

}
}

Switch选择结构

多选择结构 switch case,switch中的变量类型可以是:byte 、short、int、char、String(JavaSE7)

1
2
3
4
5
6
7
8
9
10
11
12
switch(expression){
//switch简单理解为匹配一个值
case value:
//语句
break;
//一定要写break,不然会出现break穿透现象,即后续结果都会输出
case value :
//语句
break;
default:
break;
}

While循环结构

1
2
3
while(布尔表达式){
//循环内容
}
  1. 只要布尔表达式为true,则一直循环
  2. 大多数情况会设置表达式让循环停止
  3. 尽量避免死循环

例子:输出1+2+3+4+5+….+100

1
2
3
4
5
6
7
i=0;
sum = 0 ;
while(i<=100){
sum = sum + i;
i++;
Sys.out(i);
}

DoWhile循环结构

do…while循环至少会进入循环一次

与while的区别

​ while先判断后执行,dowhile是先执行再判断

​ dowhile至少会执行一次

1
2
3
do{
//代码语句
}while(布尔表达式)

For循环结构

1
2
3
for(初始化;布尔表达式;更新){
//代码语句
}

注意:最先执行的初始化步骤,可以声明一种类型,但可初始化一个或者多个循环控制变量,也可以是空语句。

​ 然后,检测布尔表达式的值。如果为true,循环体继续,如果为false,循环终止,开始执行循环体后面的语句。

执行一次循环体以后,更新循环体控制变量。

打印九九乘法表

1
2
3
4
5
6
7
8
9
public static void main(String[] args) {
for (int j = 1; j <= 9; j++) {
for (int i = 1; i <= j; i++) {
System.out.print(j+"*"+i+"="+(j*i) + "\t");
}
System.out.println();
}

}
  1. 先写一个for循环,实现第一列
1
2
3
4
5
6
public static void main(String[] args) {
for(int i = 1; i <= 9; i++){
System.out.println(i+"*"+i+"="+(1*i));
}

}
1
2
3
4
5
6
7
8
9
1*1=1
1*2=2
1*3=3
1*4=4
1*5=5
1*6=6
1*7=7
1*8=8
1*9=9
  1. 再写一个for循环包裹上一个for循环
1
2
3
4
5
6
7
public static void main(String[] args) {
for (int j = 1; j <= 9; j++) {
for (int i = 1; i <= 9; i++) {
System.out.println(1+"*"+i+"="+(1*i));
}
}

注意:此时已经能够输出乘法表,但是有多余的部分,需要去重,即把 1 换成 j

1
2
3
4
5
6
7
public static void main(String[] args) {
for (int j = 1; j <= 9; j++) {
for (int i = 1; i <= j; i++) {
System.out.println(j+"*"+i+"="+(j*i));

}

  1. 此时乘法表已经完成,剩下就是排版,即再输出后面加“\t” 以及 换行即可
1
2
3
4
5
6
7
8
public static void main(String[] args) {
for (int j = 1; j <= 9; j++) {
for (int i = 1; i <= j; i++) {
System.out.print(j+"*"+i+"="+(j*i)+"\t");

}
System.out.println();
}

增强For循环

1
2
3
4
5
6
public static void main(String[] args) {
int [] numbers = {10,20,30,40,50};
for(int i :numbers){
System.out.println(i);
}
}

break、continue、goto

break: 循环的主体部分, 强制退出循环

continue:用于终止某一次循环

goto:保留字,类似前端的锚点

方法的定义和调用

方法:语句的集合,即函数。

1
2
3
4
5
6
7
8
main(){
int c = add(1,2);
Sys.out(c)
}

public static int add (int a ,int b){
return a+b;
}

方法的格式: 修饰符 返回值类型 方法名 (参数类型,参数名 ){

。。。

方法体

。。。

return 返回值;

}

方法的调用

  • 静态方法,static修饰

类一实现方法

1
2
3
4
public  static  void sayHello() {
System.out.println("Hello");
return ;
}

类二可以直接调用

1
2
3
public static void main(String[] args) {
sayHello();
}

第二种情况:方法a可以直接调用方法b

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//第一种普通方法
public class Demo02 {
public void a(){
b();
}
public void b(){
}
}
//第二种静态方法
public class Demo02 {
public static void a(){
b();
}
public static void b(){
}
}

注意:以下情况会报错,原因是static方法与类同时加载,此时b还没有创建,无法调用

1
2
3
4
5
6
7
public class Demo02 {
public static void a(){
b();
}
public void b(){
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  //调用举例1
public static void main(String[] args) {
Demo02 demo = new Demo02();
demo.a(1,2);
}
public int a(int a,int b){
return a + b;
}
public static void b(){

}
//调用举例2
public static void main(String[] args) {

Demo.a(1,2);
}
public static int a(int a,int b){
return a + b;
}
public static void b(){

}
  • 非静态方法

类一非静态方法,无法夸类调用,可以实例化这个类,即new 一个类调用方法。

1
2
3
4
public void sayHello() {
System.out.println("Hello");
return ;
}

类二

1
2
3
4
5
6
7
8
9
10
11
public static void main(String[] args) {
new 类名().方法()
new Student().sayHello();
// 一般写成这种格式
// 对象类型 对象名字 = 对象的值
Student student = new Student()
// 使用
student.sayHello();

sayHello();
}

实参与形参数的类型要一致

值传递与引用传递

值传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Demo02 {
//值传递
public static void main(String[] args) {
int a= 1;
System.out.println(a);// 1
Demo02.change(a);
System.out.println(a);// 1,原因是Java中是值传递,change方法中没有返回值,int a 是形参
}
//注意,此处的返回值为空
public static void change(int a){
a=10;
}

}


// 输出结果
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
1
1

Process finished with exit code 0

引用传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Demo02 {
//引用传递:传一个对象,本质还是值传递
public static void main(String[] args) {
Student student = new Student();
System.out.println(student.name);// null
Demo02.change(student);
System.out.println(student.name);// Student
}

public static void change(Student student){
// 此处student是一个对象:指向的是Student这个类-----Student student = new Student();这是
// 一个具体的类,可以改变属性!
student.name = "Student";

}
}

// 定义了一个Student类,有一个属性:name
class Student{
String name;// 默认值是 null
}

方法的重载

重载就是在同一个类中,有相同的函数名称,但是行参不同的函数。

规则

  • 方法的名称必须相同。
  • 参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)。
  • 方法的返回类型可以相同也可以不同
  • 仅仅返回类型不同不能够称为方法的重载

可变参数

  • JDK1.5开始,java支持传递同类型的可变参数给一个方法。
  • 在方法声明中,在指定参数类型后面加一个省略号(…)。
  • 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void printMax( double...numbers){
if(numbers.length == 0){
System.out.println("No argument passed");
return;
}
double result = numbers[0];

//排序
for (int i =1 ; i<numbers.length;i++){
if(numbers[i]>result){
result = numbers[i];
}
}
System.out.println("The max value is "+ result);
}

递归讲解

递归:A方法调用A方法!就是自己调用自己

结构

  • 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
  • 递归体:什么时候需要调用自身方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(String[] args) {
System.out.println(f(10));


}

public static double f(double n ){
if (n == 1) {
return 1;
}else{
return n*f(n-1);
}
}

数组

  • 相同类型数据的有序集合。
  • 相同类型的若干个数据,按照一定的先后顺序排列组合而成。
  • 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们。

数组的声明与创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static void main(String[] args) {
//变量的类型 变量的名字 = 变量的值;
//1.定义
int [] nums ;
// 这里面可以放10个int类型的数字
nums = new int[10];
double[] ds = new double[10];
nums[0] = 0;
nums[1] = 1;
nums[2] = 2;
nums[3] = 3;
nums[4] = 4;
nums[5] = 5;
nums[6] = 6;
nums[7] = 7;
nums[8] = 8;
nums[9] = 9;
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
System.out.println(sum);
}
}

特点

  • 数组的长度是确定的,数组一旦被创建,其大小就是不可以改变的。
  • 其元素必须是同类型,不允许出现混合类型。
  • 数组中的元素可以是任何数据类型,包括基本的数据类型和引用数据类型。
  • 数组变量属于引用类型,数组也可以看成是对象,数组中的每一个元素相当于该对象的成员变量。
  • 数组的本身就是对象,java中对象是在堆中的,因此数组无论保存原始数据类型还是其他对象类型,数组对象本身是在堆中的

三种初始化以及内存分析

1
2
3
4
5
6
7
8
9
10
public static void main(String[] args) {
//静态初始化

int [] a = { 0,1,2,3,4,5};

//动态初始化,包含默认初始化(int类型是0,String 类型是null)
int [] b = new int[10];
b[0] = 10; //赋值

}

下标越界

超出数组长度,会报错(下标越界)

数组的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    public static void main(String[] args) {
int[] array = { 1,2,3,4,5,6,7,8,9,10};

//反转数组

//打印数组
for (int i = 0; i < array.length; i++) {
System.out.println(i);
}
//求和
int sum = 0;
for (int i = 0; i < array.length; i++) {
sum += array[i];
System.out.println("求和结果是"+sum);
}
// 查找最大元素
int max = array[1];
for (int i = 1; i < array.length; i++) {
if (array[i]>max) {
max = array[i];
}
}

二维数组

1
2
3
4
5
public static void main(String[] args) {
int [][] a = {{0,1}};
System.out.println(a[0][0]);
}

Arrays类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void main(String[] args) {
int [] array = {1, 2, 3, 4, 5, 6, 7, 8};
int [] b = new int[10];
//打印
System.out.println(array);
System.out.println(Arrays.toString(array));
//排序(升序)
Arrays.sort(array);
System.out.println(Arrays.toString(array)) ;
//赋值
Arrays.fill(b,2,4,1);
System.out.println(Arrays.toString(b));
}
// 重写
public static void h (int[] array){
for (int i = 0; i < array.length; i++) {
if (i == 0) {
}
System.out.println(Arrays.toString(array));
}
}

冒泡排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
    public static void main(String[] args) {
int [] a = {1,4,5,62,24,56,35,99,2,35,563,9};
int[] sort = sort(a); //调用自己写的方法,返回一个排序后的数组
System.out.println(Arrays.toString(sort));
}

//冒泡排序
//1.比较数组中,两个相邻的元素,如果第一个比第二个大,我们就想换位置
//2.每一次比较,都会产生出一个最大或者最小的数字
//3.下一轮可以少排序一次
//4.依次循环,直到结束
public static int[] sort(int[] array){
// 临时变量
int temp = 0;
//外层循环,判断需要走多少次
for (int i = 0; i < array.length-1; i++) {
boolean flag = false;//减少没有意义的比较
// 内层循环,比较两个数,如果第一个数比第二个数大,则交换位置
for (int j = 0; j <array.length-1-i; j++){
if(array[j+1]<array[j]){
temp = array[j];
array[j] =array[j+1];
array[j+1] =temp;
flag = true;

}
}
if (flag== false) {
break;
}
}
return array;
}

稀疏数组

  • 当一个数组中大部分元素为0(五子棋),或者为同一个值的数组时,可以使用稀疏数组来保存该数组。

  • 稀疏数组的处理方式是:

                  1. 记录数组一共有几行几列,有多少个不同的值
                  1. 把具有不同的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模
    

我真牛逼,这都写出来了,自己写的自己都看不懂了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
public class Demo01 {
public static void main(String[] args) {
//1. 创建一个二维数组 11 × 11 0 : 没有棋子 ,1 : 黑棋 2:白棋
int [][] array1 = new int[11][11];
array1[1][2] = 1;
array1[2][3] = 2;
//输出原始的数组
System.out.println("输出原始的数组");
for (int [] ints : array1) {
for (int anInt: ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
System.out.println("================================================");
//转换为稀疏数组
//拿到有效值的个数
int sum = 0;
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if (array1[i][j] != 0 ) {
sum++;
}
}
}
System.out.println("有效值的个数:" + sum);

// 创建稀疏数组
int [][] array2 = new int[sum+1][3];
array2[0][0] = 11;
array2[0][1] = 11;
array2[0][2] = sum;

//遍历二维数组,将非零的值,存放到稀疏数组中

int count = 0;
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array1[i].length; j++) {

if (array1[i][j] != 0) {
count++;
array2[count][0] = i;
array2[count][1] = j;
array2[count][2] = array1[i][j];
}
}
}
// 输出稀疏数组
System.out.println("稀疏数组");

for (int i = 0; i < array2.length; i++){
System.out.println(array2[i][0]+"\t"
+array2[i][1] + "\t"
+array2[i][2] + "\t"
);
}
System.out.println("================================================");
System.out.println("还原");
// 读取稀疏数组
int [][] array3 = new int[array2[0][0]][array2[0][1]];
// 给元素还原值
for(int i=1; i<array2.length; i++){
array3[array2[i][0]][array2[i][1]] = array2[i][2];
}
// 打印
System.out.println("输出原始的数组");
for (int [] ints : array3) {
for (int anInt: ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
}
}

面向对象

面向过程思想

  • 步骤清晰简单,第一步做什么,第二步做什么……
  • 面对过程适合处理一些较为简单的问题

面向对象思想

  • 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面对过程的思索。
  • 面对对象适合处理复杂的问题,适合处理需要多人协作的问题!

对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面象对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。

面向对象编程

  • 以类的方式组织代码,以对象的组织(封装)数据。
  • 抽象
  • 三大特性:
  1. 封装
  2. 继承
  3. 多态

类与对象

终于搞明白了这个玩意[苦涩][苦涩]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class Demo02 {

public static void main(String[] args) {
// 类:抽象的,需要实例化
// 类实例化后会返回一个自己的对象!
//student 对象就是一个具体的Student类的具体实例
Student student1 = new Student();
Student student2 = new Student();
student1.name = "xiaoming";
student1.age =15;
System.out.println(student1.name);
System.out.println(student1.age);

System.out.println("================================================================");
System.out.println(student2.name);
System.out.println(student2.age);
}


}

// 学生类,这是一个模板,是对象共同拥有的属性,一个模板可以new 很多对象
class Student{
// 属性: 字段
String name;
int age;

//方法

public void change(){
System.out.println("Student");

}
}


//输出
xiaoming
15
================================================================
null
0

构造器

  • 一个类即使什么都不写,只要被创建了就有一个默认的方法,即构造方法。
  • 1.必须和类的名字相同
  • 2.必须没有返回类型,也不能写void
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Demo02 {

public static void main(String[] args) {
Student student = new Student();
System.out.println(student.name);// null
}
}

// 学生类,这是一个模板,是对象共同拥有的属性,一个模板可以new 很多对象
class Student{
String name;
// 1.无参构造,可以实例化初始值
// 2.使用new关键字必须要有构造器
public Student(){
// this.name = "Student";
}

// 有参构造,一旦定义了有参构造,无参必须显示定义 ,即无参中的this.name = "Student";必须去掉,不然会报错,当new一个对象的时候
// 因为有两个方法,所以会出现方法的重载,传参数则进入有参构造

// 草了,这是真的神奇,融会贯通了
public Student(String name){
// this.name = name(属性中的String name;)
//name 指的是形参中的(String name)
this.name = name;
}
}

构造器

  • 和类名相同
  • 没有返回值

作用

  • new 本质在调用构造方法
  • 初始化对象的值

注意点

  1. 定义参数构造后,如果想使用无参构造,显示的定义一个无参的构造

对象在内存中的创建过程图

类与对象的小结

  1. 类与对象

​ 类是一个模板:抽象,对象是一个具体的实例

  1. 方法

​ 定义与调用

  1. 对象的引用

​ 引用类型: 基本类型(8)

​ 对象是通过引用来操作的:栈—->堆

  1. 属性:字段Filed 成员变量

​ 默认初始化:

​ 数字:0 0.0

​ char : u0000

​ boolean : false

​ 引用: null

修饰符 属性类型 属性名 = 属性值!

  1. 对象的创建和使用

    • 必须使用new 关键字创造对象,构造器 Student student = new Student();
    • 对象的属性 student.name
    • 对象的方法 student.say();
    1. 类:

      静态的属性 属性

      动态的方法 方法

封装

  • 该露的露,该藏的藏

    我们设计要追求 “高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用

  • 封装(数据的隐藏)

    通常,应禁止直接访问一个对象中数据的实际表示,而应该通过操作接口来访问

  • 属性私有:Get/Set

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package com.woniu;
public class Demo02 {
public static void main(String[] args) {
Student student = new Student();
student.setName("Student");
System.out.println(student.getName());
}
}
class Student{
private String name;
private int age;
private int id;
private String email;
public Student() {
//属性
this.name = name;
this.age = age;
this.id = id;
this.email = email;
}
//无参方法
public Student() {
this.name = name;
this.age = age;
this.id = id;
this.email = email;
}
//Get
public String getName() {
return name;
}
//Set 注意:可以设置属性,进行判断 age
public void setName(String name) {
this.name = name;
}
public int getAge() {
if(age<20 || age >100){
age = 18;
}else{
this.age = age;
}
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}
}

特点

  • 提高程序的安全性,保护数据
  • 隐藏代码的实现细节
  • 统一接口
  • 系统可维护增加了

继承

  • 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
  • extends的意思是“扩展”。子类是父类的扩展
  • java中只有单继承,没有多继承!
  • 继承是类与类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
  • 继承关系的两个类,一个为子类(派生类),一个是父类(基类)。子类继承父类,使用关键字extends来表示。
  • 子类与父类之间,从意义上讲应该具有“is a”的关系。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Demo02 {
public static void main(String[] args) {
Student student = new Student();
student.say();
}
}
class Student extends Person{
}
// 父类
class Person {
public void say() {
System.out.println("Hello ");
}
}
class Teacher {
}

  • object类
  • super
  • 方法重写

Supper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class Demo02 {

public static void main(String[] args) {
Student student = new Student();
//student.test("test");
// student.test1();
}
}
class Student extends Person{
private String name = "Student";

public Student() {
// 隐藏代码,调用了父类的无参构造方法
super();//调用了父类的构造方法,必须在子类的第一行
System.out.println("子类无参");
}
public void say1() {
System.out.println("Hello,world!");
}
public void test(String name){
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name);
}
public void test1(){
say1();
this.say1();
super.say();
}
}
// 父类
class Person {
public Person() {
System.out.println("父类无参");
}
protected String name = "Johnny";
public void say() {
System.out.println("Hello ");
}
}
class Teacher {

}

supper注意点:

  1. supper调用父类的构造方法,必须在构造方法中的地一个
  2. supper 必须只能出现在子类的方法中或者构造方法中
  3. supper 和 this 不能同时调用构造方法

Vs this :

  • 代表的对象不同:

​ this : 本身调用者这个对象

​ supper: 代表父类对象的应用

  • 前提

    ​ this:没有继承也可以使用

    ​ supper:只能在继承中使用

  • 构造方法

    ​ this():本类的构造

    ​ supper():父类的构造

方法的重写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Demo02 {
public static void main(String[] args) {
//静态的方法和非静态的方法区别很大!
// 静态方法 : 方法的调用只和左边,定义的数
// 非静态方法:重写
Demo03 demo03 = new Demo03();
demo03.say();
Demo04 demo04 = new Demo03();
demo04.say();
}
}
//继承
class Demo03 extends Demo04 {

// @Override
public static void say() {
System.out.println("Demo03===>Hello World");
}
}
class Demo04 {
public static void say() {
System.out.println("Demo04===>Hello World");
}
}


Demo03===>Hello World
Demo04===>Hello World

Process finished with exit code 0

重写

  • 方法名必须相同
  • 参数列表必须相同
  • 修饰符:范围可以扩大但不能缩小: pubilic >Protected>Default>private
  • 抛出的异常:范围,可以缩小,但不能扩大: ClassNoFoundException –> Exception(大)

重写,子类的方法和父类不需要一致:方法体不同!

为什么要重写:父类的功能,子类不一定需要,或者不一定满足!

多态

  • 动态编译: 类型 :可扩展性
  • 即同一方法可以根据发送的对象的不同而采取多种不同的行为方式
  • 一个对象的实际类型是确定的,但可以指向对象的引用类型有很多
  • 多态存在的条件
    1. 有继承关系
    2. 子类重写父类的方法
    3. 父类引用指向子类对象
  • 注意
    1. 多态是方法的多态,属性没有多态性
    2. 父类和子类,有联系 类型转换异常! ClassCastException!
    3. 存在条件 :继承关系,方法需要重写,父类引用指向子类对象 Father f1 = new Son();
    4. 以下没有多态
      - static 方法
      - final 常量
      - private方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class Demo02 {
public static void main(String[] args) {

//一个对象的实际类型是确定的
// new Demo03();
// new Demo04();

// 可以指向的引用数据类型就不确定了 : 父类的引用指向子类

// Demo03 能够调用的方法都是自己的或者是继承父类的!
Demo03 demo = new Demo03();
// Demo04 父类型,可以指向子类,但是不能调用子类独有的方法
Demo04 demo2 = new Demo03();
Object demo3 = new Demo03();
// 对象能够执行哪些方法,主要看对象左边的类型,和右边的关系不大!
demo.say();
demo2.say();
demo.run();
// 强制转换
((Demo03)demo2).run();
//子类重写了父类的方法,执行子类的方法
}
}
//继承
class Demo03 extends Demo04 {
@Override
public void say() {
System.out.println("Demo03===>son");
}
// 子类独有的方法
public void run() {
System.out.println("Run demo");
}
}
class Demo04 {
public void say() {
System.out.println("Demo04===>father");
}
}


Demo03===>son
Demo03===>son

Process finished with exit code 0

instanceof和类型转换

instanceof 判断类之间的关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public class Demo02 {
public static void main(String[] args) {
// object > String
// object > Person > Teacher
// object > Person > Student
Object object = new Student();

System.out.println(object instanceof Student); //true
System.out.println(object instanceof Person); //true
System.out.println(object instanceof Teacher); //false
System.out.println(object instanceof Object); //true
System.out.println(object instanceof String); // false
System.out.println("================================================================");
Person person = new Student();
System.out.println(person instanceof Student); //true
System.out.println(person instanceof Person); //true
System.out.println(person instanceof Teacher); //false
System.out.println(person instanceof Object); //true
//System.out.println(person instanceof String); // 编译报错
System.out.println("================================================================");

Student student = new Student();
System.out.println(student instanceof Student); //true
// System.out.println(student instanceof Teacher); //false
System.out.println(student instanceof Person); //true
System.out.println(student instanceof Object); //true
}
}

class Person{
public void run(){
System.out.println("Runnable");
}

}
class Student extends Person{

}
class Teacher extends Person{

}


true
false
true
false
================================================================
true
true
false
true
================================================================
true
true
true

Process finished with exit code 0

类型转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Demo02 {
public void main(String[] args) {
// object > String
// object > Person > Teacher
// object > Person > Student


Student student = new Student();
// 类之间的转换 父 子
// 高 低
Person person = new Student();
// student 将这个对象转换为Student类型,我们就可以使用Student类型的方法!
// 低 高
((Student)student).go();
}
class Person {
public void run() {
System.out.println("Runnable");
}
}
class Student extends Person {
public void go() {
System.out.println("GO");
}
}
class Teacher extends Person {
}
}
  • 父类引用指向子类的对象
  • 把子类转换为父类,向上转型
  • 把父类转换为子类,向下转型;强制转换,丢失精度(丢失方法)
  • 方便方法的调用,减少重复的代码!

static

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Demo02 {
public static void main(String[] args) {
Student student = new Student();
System.out.println("================================================");
Student student1 = new Student();
}
}
class Student{
// 默认,赋初始值
{
System.out.println("默认代码块");
}
// 静态代码块
//只执行一次
static {
System.out.println("静态代码块");
}
public Student() {
System.out.println("构造方法");
}
}

抽象类

  • abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。

  • 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。

  • 抽象类,不能使用new 关键字来创建对象,它是用来让子类继承的。

  • 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。

  • 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。

1
2
3
4
5
6
7
8
9
10
11
12
// abstrack 抽象类: 类  extends: 单继承~ (接口可以多继承)
public abstrack class Action{

//抽象类相当于约束,子类或者子子类去实现它: 约束!
// 抽象类中可以写普通方法~
// 抽象方法必须在抽象类中
// 抽象的抽象: 约束

//new 一个抽象类,抽象类是有构造方法的。 因为,虽然抽象类不能直接被实例化,但是继承抽象类的子类毫无疑问能被实例化,在其子类被实例化时,必然执行子类的构造方法, 接口是没有构造方法的。
//
public abstracct void doSomething();
}

抽象类存在的意义和作用

  • 抽象是将共性抽离出来,产生抽象性概念非具体。

  • 抽象类和抽象方法作用: 使类的抽象性明确起来,告诉用户和编译器打算怎么使用他们。抽象类还是很有用的重构工具,因为它们使得我们可以很容易地将公共方法沿着继承层次结构向上移动。

  • 抽象类不可实例化,抽象类包含普通方法和抽象方法。抽象方法只需声明无需方法体。

  • 子类继承抽象类,父类的抽象方法必须被子类重写,普通方法可不需要重写。

接口的定义与实现

  • 普通类:只有具体的实现

  • 抽象类:具体实现和规范(抽象方法)都有!

  • 接口:只有规范!

  • 接口就是规范,定义的是一组规则

  • 接口的本质是契约,规定好后大家都接受。

作用

  • 约束
  • 定义一些方法,让不同的人实现~ 10 ——— 1
  • public abstract
  • public statis final
  • 接口不能被实例化~,接口中没有构造方法~
  • implemments可以实现多个接口
  • 必须重写接口中的方法

接口

1
2
3
4
5
6
7
8
9
10
// interface  定义关键字 ,接口都需要有实现类
public interface UserService {

// 接口中的所有定义的方法其实都是抽象的 public abstract
void add(String username);
void delete(String username);
void update(String username);
void query(String username);
}

实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 抽象类: extends
// 类 可以实现接口 implements 接口
// 实现了接口的类,就需要重写接口中的方法~

// 多继承~ 利用接口实现多继承
public class UserServiceImpl implements UserService{
@Override
public void add(String username) {

}

@Override
public void delete(String username) {

}

@Override
public void update(String username) {

}

@Override
public void query(String username) {

}
}

N种内部类

  • 内部类就是在一个类的内部再定义一个类,比如,A类中定义了一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了
  1. 成员内部类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Circle {
private double radius = 0;
public static int count =1;
public Circle(double radius) {
this.radius = radius;
}

class Draw { //内部类
public void drawSahpe() {
System.out.println(radius); //外部类的private成员
System.out.println(count); //外部类的静态成员
}
}
}

2.局部内部类

局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class People{
public People() {

}
}

class Man{
public Man(){

}

public People getWoman(){
class Woman extends People{ //局部内部类
int age =0;
}
return new Woman();
}
}

3.匿名内部类

匿名内部类应该是平时我们编写代码时用得最多的,在编写事件监听的代码时使用匿名内部类不但方便,而且使代码更加容易维护。下面这段代码是一段Android事件监听代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
scan_bt.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub

}
});

history_bt.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub

}
});

4.静态内部类

  静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Test {
public static void main(String[] args) {
Outter.Inner inner = new Outter.Inner();
}
}

class Outter {
public Outter() {

}

static class Inner {
public Inner() {

}
}
}

2022-10-09 午


Java基础
https://lfrok.top/2022/10/09/Java/java基础/
作者
B612🚀
发布于
2022年10月9日
许可协议