Java多概念

学习方法

先只通过代码写注释,再只通过注释写代码

先解决问题,再发现更多方案,最后选择最优


计算机基础

快捷键

ctrl d

ctrl y

ctrl shift ↑ ↓

ctrl d

alt 可以区域复制,批量输入


数据类型

模块可以导入和删除

包可以用来区分重名的类

‘ ’ 里面有且只能有一个字符

“ ”随意

可以输出 true false ,但不能输出null

.java


命名规范

类 接口 每个单词首字母大写

HelloWord

变量 方法 第二个单词开始首字母大写

zhangNameAge

常量 全部大写,单词用_隔开

MAX_VALUE

包 全部小写 多级包用 . 隔开

cn.itcast


类型转换


自动类型转换

double 8个字节

int 4个字节

byte 1个字节

int + byte =int(自动转换为4个字节)

byte,short,char->int->long–>float->double


强制类型转换

新建类 ctrl alt insert

类型兼容的情况下

数据类型 变量名 = (目标数据类型) 初始化值;

double d = 10int a  =int)d;

常量相加,直接运算,结果不能超过数据类型范围

byte b1 = 3byte b2 = 4byte b3 = 3 + 4 ; ✔

变量相加,自动提升数据类型,再进行运算,防止数据类型不够用

byte b4 =byte )( b1 + b2);变量 + 变量 ;

byte b5 =byte )( b1 +4);变量 + 常量 ;

ASCII码表

sout(’ 字符 ‘ + 0);


赋值运算符

+= -= *= /= %= (取余)

b += a ( b = b +a )


关系运算符

== 判断是否等

!= 判断是否不等

> 判断

>= 判断

< 判断

<= 判断

成立为true,不成立为false


逻辑运算符

& 与 不能有假

| 或 有真就行

! 非 取反

^ 逻辑异或,a^b,异同的意思,同为false


短路逻辑运算符

&& 双与 前面出现false,后面不执行

|| 双或 前面出现true,后面不执行


三元运算符

类似if else循环

(关系表达式) ? 表达式1 : 表达式2 ;

关系表达式为true,则执行 表达式1

否则执行 表达式2


基础语法

方法

例如: 让我们获取元素10和20的最大值, 我们可以通过if语句或者三元运算符实现, 如果再让我们获取22和11之间的最大值, 我们还需要把刚才的逻辑代码在写一次. 这样做很繁琐. 针对于这种情况, 我们就可以把获取两个整数最大值的逻辑代码 封装 到方法中, 当我们需要比较的时候, 直接调用方法就可以了. 这样做, 非常方便.


定义格式

修饰符 返回值的数据类型 方法名(参数类型 参数名1, 参数类型 参数名2) {  //这里可以写多个参数 

    
    //方法体;     
    
   return    // 具体的返回值; 
}

 public static	void   main  (String[]     args)  {
  
}

}


格式解释

  • 修饰符: 目前记住这里是固定格式public static

  • 返回值的数据类型: 用于限定返回值的数据类型的.

    注意:

    ​ 返回值的数据类型是int类型, 则说明该方法只能返回int类型的整数.

    ​ 如果方法没有具体的返回值, 则返回值的数据类型要用void来修饰.

  • 方法名: 方便我们调用方法.

  • 参数类型: 用于限定调用方法时传入的数据的数据类型.

    例如: 参数类型是String类型, 说明我们调用方法时, 只能传入字符串.

  • 参数名: 用于接收调用方法时传入的数据的变量.

  • 方法体: 完成特定功能的代码.

  • return 返回值: 用来结束方法的, 并把返回值返回给调用者.

    解释: 如果方法 没有明确的返回值, 则return关键字可以省略不写.


方法重载

同一个类中, 出现方法名相同, 但是**参数列表不同 **(个数或类型不同) 的两个或以上的方法时称为方法重载

使用场景

定义方法compare(), 用来比较数据是否相等.

  • 要求:兼容所有的整数类型, 即(byte, short, int, long)

示例:

public class MethodDemo01 {
  public static void main(String[] args) {
    //定义不同数据类型的变量
    byte a = 10;
    byte b = 20;
    short c = 10;
    short d = 20;
    int e = 10;
    int f = 10;
    long g = 10;
    long h = 20;
      
    // 调用
    System.out.println(compare(a, b));
    System.out.println(compare(c, d));
    System.out.println(compare(e, f));
    System.out.println(compare(g, h));
  }

  // 两个byte类型
  public static boolean compare(byte a, byte b) {
    System.out.println("byte");
    return a == b;
  }

  // 两个short类型的
  public static boolean compare(short a, short b) {
    System.out.println("short");
    return a == b;
  }

  // 两个int类型的
  public static boolean compare(int a, int b) {
    System.out.println("int");
    return a == b;
  }

  // 两个long类型的
  public static boolean compare(long a, long b) {
    System.out.println("long");
    return a == b;
  }
}



注意事项

方法与方法之间是平级关系, 不能嵌套定义.

方法必须先创建才可以使用, 该过程称为: 方法定义.

方法自身不会直接运行, 而是需要我们手动调用方法后, 它才会执行, 该过程称为方法调用.

方法的功能越单一越好.

定义方法的时候写在参数列表中的参数, 都是: 形参.

形参: 形容调用方法的时候, 需要传入什么类型的参数.

调用方法的时候, 传入的具体的值 (变量或者常量都可以), 叫实参.

实参: 调用方法时, 实际参与运算的数据.


方法调用


三个明确

定义方法时, 要做到三个明确

  • 方法名, 小驼峰命名法, 要见名知意
  • 方法的参数列表: 需要给方法什么数据
  • 返回值类型: 方法会返回给我们一个什么类型的数据.

键盘录入

Scanner sc = new Scanner(System.in);

int a =sc.nextint();

if

如果if的控制(执行)语句只有一行代码,不用大括号

if(a==0)
   		  a++;
else 
   		a--;

switch

 Scanner sc =  new Scanner(System.in);
    System.out.println("请录入一个月份: ");
    int month = sc.nextInt();
     switch  (month) {
      case 12:
        System.out.println("冬季");
       break;
      case 1:
        System.out.println("冬季");
       break;
  ……………………
      default:
        System.out.println("没有这样的日期");
       break;

case穿透

case的后面break不写,不会在判断下一个case的值,直到遇到break,或者switch结束。

使用场景,两个case,break一个结果

  switch(month) {
      case 12:
      case 1:
      case 2:
        System.out.println("冬季");
       break;
      case 3:
      case 4:
      case 5:
        System.out.println("春季");
       break;
      default:
        System.out.println("没有这样的日期");
       break;

Default语句不放最后也行,任意位置,放最后规范

最后一个break和第一个右括号都可以结束语句,所以break能省略


for循环

固定循环次数

forint i = 0;i < 10 ; i++)

for( 初始化条件1 ; 判断条件2 ;控制条件3 ){ 循环体 ;}

while循环

while(判断条件2) {    //循环体3;    //控制条件4;} while (i <= 100) {            if (i % 2 == 0)                sum += i;//循环体----循环代入i            i++;//控制条件----控制i值        }

Do While

 int i = 1;do{	System.out.println("Hello World! " + i);    //循环体,循环代入        	i++;					   //控制条件,控制i值        		}while(i <= 10);			//判断条件,判断跳出条件

三种循环之间的区别

do.while循环和其他两个循环之间的区别

  • do.while循环是先执行一次, 后判断.

  • 而其他两个循环都是先执行判断条件, 然后决定是否执行循环体.

for循环和其他两个循环之间的区别

  • for循环执行结束后, 初始化条件就不能继续使用了.

  • 而其他两个循环执行结束后, 初始化条件还可以继续使用.

总结:do-while 先执行操作,再判断条件,for 循环结束后,初始化条件不能继续用


Break

 for(int i = 1; i <= 10 ; i++) {     if(i == 5)        break; //if为true,break for循环      System.out.println("Hello World!" + i);    }    System.out.println("end");

continue

 for (int i = 1; i <= 10; i++) {            if (i % 3 == 0)//if为true,结束本次循环                continue;// if为false, continue            System.out.println(i);        }        System.out.println("end");

参数传递

数组

数组, 就是一种容器

数组用来存储多个同类型元素

创建数组:

//动态初始化
		int[] arr1 = new int[3];		//推荐.
        
       // int arr2[] = new int[3];
//静态
        //直接传入存储数据`11, 22, 33`, 由系统指定长度.
      //  int[] arr3 = new int[]{11, 22, 33};

        int[] arr4 = {11, 22, 33};	

//数组索引
System.out.println(arr[1]);	//打印结果是: 22
arr[1] = 222;

内存解释

内存是计算机中的重要原件,也是临时存储区域,作用是运行程序。我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的,必须放进内存中才能运行,运行完毕后 会清空内存

即: Java虚拟机要运行程序,必须要对内存进行空间的分配和管理。为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。


JVM的内存划分

: 存储局部变量以及所有代码执行的.

局部变量: 指的是定义在方法中, 或者方法声明上的变量.

特点: 先进后出.

: 存储所有new出来的内容(即: 对象).

特点: 堆中的内容会在不确定的时间, 被GC回收.

方法区: 存储字节码文件的.

字节码文件: 指的是后缀名为.class的文件.

本地方法区:

和系统相关, 了解即可.

寄存器

和CPU相关, 了解即可.


打印数据地址

public class ArrayDemo03 {
   public static void main(String[] args) {
    int[] arr =  new int[3];
    System.out.println(arr[0]); //打印数组中的第一个元素, 值为: 0 
    System.out.println(arr);   //[I@1540e19d 
  }
}

其中 [I@1540e19d是 arr 数组的地址值 ,


调用方法

无参无返回值

当一些代码被反复使用时,可以把它们提取出来,放(封装)到一个方法里,以方法的形式来使用这些代码-----可以提高代码的复用性, 方便维护程序.

  • 格式

    	public  static void printHello()  {
     System.out.println("Hello World!);
    }
    
  • 调用

	printHello()

有参无返回值

调用方法时, 我们需要传入具体的参数, 但是方法执行完毕后, 并不会给我们返回具体的结果.

  • 格式
public static void 方法名(参数类型 参数名1, 参数类型 参数名2) {	//这里可以写多个参数
  //方法体;
}
  • 调用
方法名(参数值1, 参数值2);	

无参有返回值

调用方法时, 我们不需要传入具体的参数, 但是方法执行完毕后, 会给我们返回具体的结果.

  • 格式
public static int sum() {
  Scanner
      //或者
    //静态参数
  return  sum;
}
  • 调用格式

    • 直接调用, 无意义
    sum();
    
    • 输出调用,演示
    System.out.println(sum());
    
    • 赋值调用, 实际开发中推荐使用
    int value = sum();
    

有参有返回值

调用方法时, 我们不仅需要传入具体的参数, 方法执行完毕后, 还会给我们返回具体的结果

  • 格式
public static 返回值的数据类型 方法名(参数类型 参数1, 参数类型 参数2) {
    //方法体;
    return 具体的返回值;
}
  • 调用

    • 直接调用

      方法名(参数值1, 参数值2);	
      
    • 输出调用

      System.out.println(方法名());
      
    • 赋值调用

      数据类型 变量名 = 方法名();
      


参数传递

定义方法时,参数列表中的变量,我们称为形式参数.

调用方法时,传入给方法的数值,我们称为实际参数.


基础知识补充

基本类型的变量保存原始值,即它代表的值就是数值本身, 原始值一般对应在内存上的栈区(存储局部变量以及所有代码执行的);基本类型包括: byte, short, int, long, char, float, double, boolean八大基本数据类型

引用类型的变量保存引用值,引用值指向内存空间的地址代表了某个对象的引用,而不是对象本身。对象本身存放在这个引用值所表示的地址的位置。被引用的对象对应内存上的堆内存区。引用类型包括: 类类型接口类型数组

值传递:实际参数把它的值传递给对应的形式参数,函数接收的是原始值的一个拷贝, 此时内存中存在两个相等的基本类型,即实际参数和形式参数,后面方法中的操作都是对形参这个值的修改,不影响实际参数的值

引用传递:也称为地址传递、址传递。方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形式参数,函数接收的是原始值的内存地址。在方法执行中,形参和实参内容相同,指向同一块内存地址,方法执行中对引用的操作将会影响到实际对象。

一般说的改变一个String变量,其实并不是改变的这个String本身,而是用一个新的String去替换掉原来的,原来的String本身并没有变

通常 基本类型 和 String 传递是值传递形参的改变不会影响实参的改变

基本类型和引用类型的区别:基本数据类型在声明时系统就给它分配空间;而引用数据类型不同,它声明时只给变量分配了引用空间,而不分配数据空间。

总结:

基本类型通过值传递方法传递实参的原始值,函数接收到原始值cpoy为形参,方法体只能修改形参byte, short, int, long, char, float, double, boolean 这**八大基本数据类型 **和 String。

引用类型通过引用传递方法传递内存空间的地址,对应内存上的堆内存区。引用类型包括: 类类型, 接口类型 和 数组


形参是基本类型

//观察下述代码, 打印结果是什么呢? public class MethodDemo02 {    public static void main(String[] args) {        int number = 100;        System.out.println("调用change方法前:" + number);        change(number);	 //实参.        System.out.println("调用change方法后:" + number);    }    public static void change(int number) {	//形参.        number = 200;    }}

**记忆: 基本类型作为参数时, 形参的改变对实参没有任何影响. **


形参是引用类型

public class MethodDemo03 {    public static void main(String[] args) {        int[] arr = {10, 20, 30};        System.out.println("调用change方法前:" + arr[1]);        change(arr);        System.out.println("调用change方法后:" + arr[1]);    }    public static void change(int[] arr) {        arr[1] = 200;    }}

记忆: 引用类型作为参数时, 形参的改变直接影响实参.


Debug

步骤:    1. 加断点, 哪里不会点哪里.    2. 运行加了断点的程序, 注意: 不要选择run, 要选择debug(就是小蜘蛛)    3. 开始调试后, 看哪里呢?        Debugger:   看代码执行到哪里了.        Console:    控制台, 就是查看程序运行结果的.        Variable:   就是查看 变量的变化过程的.    4. 如何进行下一步?        F7: 逐过程调试        F8: 逐行调试        F9: 逐断点调试    5. 如何删除断点?        方式1: 一个一个删除.        方式2: 批量删除.      //选择breakpoints(双红点), 移除断点即可.

面向对象

面试标准回答

概述 思想特点 举例 总结

c面向过程

java面向对象,表示现实世界,万物皆可对象化



举例

类是学生**,抽象概念,类的实例化对象,例如:成员变量:张三 23 岁成员方法:给 张三 发消息


学生类

//学生类(类:抽象概念 看不见 )
    public class Student{
        
    //成员变量(属性:描述事物外在特征)
        //先写到 类中, 方法外, 而且成员变量有默认值
    String name;	//姓名
    int age;		//年龄
    
    //成员方法(行为:事物能够做什么)
        //先不写static
    public void study() {//学习的方法
        System.out.println("键盘敲烂, 月薪过万!...");
    }
    
    public void eat() {//吃饭的方法
        System.out.println("学习饿了要吃饭!...");
    }
}

操作学生类

调用

public class StudentTest{
    public static void main(String[] args) {
        //1. 创建学生类的对象.
        Student s = new Student();
        
        //2. 访问成员变量.
        System.out.println(s.name);//输出null
        System.out.println(s.age);//输出0
        
        //3. 给成员变量赋值.
        s.name = "张三";    
        s.age = 23;
        
        //4. 访问成员变量.
        //通过  对象名.成员变量  来使用类中的成员
        System.out.println(s.name);
        System.out.println(s.age);
        
        //5. 访问成员方法.
        //通过 对象名.成员方法(参数1, 参数2) 来使用类中的成员
        s.study();
        s.eat();
    }
}

成员变量和成员方法

package com.itheima.demo02_phone;

//案例: 定义手机类, 用来描述手机的(属性, 行为)
//像这样的用来描述事物的类叫: 实体类, 也叫: JavaBean类, POJO类.
public class Phone {
    // 属性: 也叫成员变量, 就是用来描述事物的外在特征的(即: 名词)
    String brand;           //品牌
    int price;              //价格
    String color;           //颜色

    // 成员方法-行为: 打电话(call), 发短信(sendMessage)
    //打电话
    public void call(String name) {   //夯哥
        System.out.println("给" + name + "打电话!...");
    }

    //发短信
    public void sendMessage(String name) {
        System.out.println("给" + name + "发短信!...");
    }

成员变量和局部变量

记忆

  • 成员变量: 指的是定义在类中, 方法外的变量.

  • 局部变量: 指的是定义在方法中, 或者方法声明上的变量.

区别:

定义位置不同.

  • 成员变量: 定义在类中, 方法外.

  • 局部变量: 定义在方法中, 或者方法声明上.

内存中的存储位置不同.

  • 成员变量: 存储在内存.

  • 局部变量: 存储在内存.

生命周期不同.

  • 成员变量: 随着对象的创建而存在, 随着对象的消失而消失.

  • 局部变量: 随着方法的调用而存在, 随着方法的调用完毕而消失.

初始化值不同.

  • 成员变量: 有默认值.

  • 局部变量: 没有默认值, 必须先定义, 再赋值, 然后才能使用.

public class VariableDemo{
    int x;//不需默认值
    
    public void show() {
        int y = 10;//默认值,在方法内有效
        System.out.println(x);
        System.out.println(y);
    }
}

封装


Private

​ private修饰的内容只能在本类中使用

​ 封装就是隐藏对象的属性和实现细节, 仅对外提供一个公共的访问方式(get set)

package com.itheima.demo04_student;

//定义学生类(JavaBean类, 实体类, POJO类)
public class Student {
    //属性, 也叫成员变量, 即: 名词.
    String name;        //姓名.
    private int age;            //年龄

    //针对于被private修饰的变量, 需要对外提供一个公共的访问方式.
    //设置变量age的值.
    public void setAge(int a) {
        //针对于用户录入的值a, 我们可以判断
        if (a >= 0 && a <= 200) {
            //合法年龄, 就设置.
            age = a;
        }
    }
    //获取变量age的值.
    public int getAge() {
        return age;
    }

    //行为, 也叫成员方法, 即: 动词.
    public void show() {
        System.out.println(name + "..." + age);
    }
}

问题:用户直接范围age,任意设置,比如**年龄设置为负数


封装Get-Set

如果不想某些内容被直接访问,可以用private修饰,再**封装一个访问方法(Get-Set过滤条件)**来访问

//案例: 学生类的测试类
package com.itheima.demo04_student;
	public class StudentTest {
    	public static void main(String[] args) {
        //1. 创建学生类的对象.
        Student s = new Student();
        //2. 设置成员变量值.
        s.name = "刘亦菲";

        //s.age = -33;
        //以下为: 采用封装后的代码.
        //设置年龄
        s.setAge(-33);

        //获取年龄
        System.out.println(s.getAge());

        //3. 打印成员变量值.
        /*System.out.println(s.name);
        System.out.println(s.age);*/
        //System.out.println(s);      //打印地址值.
        s.show();
    }
}

意义:防止用户直接访问


继承


This

​ 哪个对象调用了方法,就用继承对象的变量, 解决局部变量和成员变量重名问题

记忆

​ 使用变量的 “就近原则”: 局部位置有就使用, 没有就去本类的成员位置

public class Student {
    //成员变量
    int x = 10;

    public void method() {
        //局部变量
        int x = 20;
        System.out.println(this.x);         //10
        System.out.println(x);              //20
    }
}

student 对象调用了 method 方法

方法里重名的 this.x 就从 继承 student 类里 的 x 的值

 Student s = new Student();
     //调用Student#method()
     s.method();

Extends

多个类有相同属性行为,将这些内容集中为一个类,其他类使用时 继承 这个类即可

public class 类A extends 类B {	    //子A 承 父业B}

开发原则: 高内聚, 低耦合.
内聚: 指的是类自己独立完成某些事情的能力
耦合: 指的是类与类之间的关系.

  • 即 : 提高子类的功能,尽量不继承父类

例:

//人类, 在这里充当的角色是父类.public class Person {   //ctrl + 字母H: 查看类的继承关系树.    //属性    private String name;    private int age;    //构造方法, 如果我们不写, 系统会默认加一个: 空参构造.    //getXxx(), setXxx()    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;    }    //行为    public void eat() {        System.out.println("人要吃饭");    }    public void sleep() {        System.out.println("人要睡觉");    }}

//案例: 学生类public class Student extends Person {    //学生类独有的功能: 学习    public void study() {        System.out.println("好好学习, 天天向上!");    }}

//案例: 老师类public class Teacher extends Person {    //老师类独有的功能: 讲课    public void teach() {        System.out.println("老师要讲课!");    }}

测试:

//1. 测试老师类        Teacher t = new Teacher();        //属性        //从Person类继承.        //方法        t.eat();        //从Person类继承.        t.sleep();      //从Person类继承.        t.teach();      //本类的独有功能.

只能继承单个,不能继承多个,可以多层继承爷>子>孙……


Super

就近原则:

​ 局部位置有**(age)**就使用,

​ 没有就去本类的**(this.age)**成员位置找,有就使用,

​ 再没有就去父类的**(super.age)**成员位置找, 有就使用, 没有就报错.

public class Son extends Father{    int age = 20;       //本类的成员变量.    public void show() {        int age = 10;   //局部变量        System.out.println(age);                //局部10        System.out.println(this.age);          //本类20        System.out.println(super.age);        //父类30    }}

继承中构造方法

访问参数时

子类空参 Son() 访问父类 Super() 空参

​ 子类带参Son(name) 访问父类super(name) 带参

public class Son extends Father{    public Son() {        super();   //子类的空参访问父类的空参        System.out.println("Son类的 空参构造, 用来初始化子类内容");    }    public Son(String name) {        super(name);        //子类的带参访问父类的带参.        //this();        System.out.println("Son类的 带参构造, 用来初始化子类内容");    }}

继承中成员方法

调用成员方法遵循"就近原则"

先调用本类,本类中没有自动去父类,父类没有则报错

调用

        Son s = new Son();        //2. 调用Son类中的方法.        s.method();   		//Son show...        s.show();			//Son method...

子类

public class Son extends Father{    public void show() {        System.out.println("Son show...");    }    public void method() {        System.out.println("Son method...");    }}

父类

public class Father {    public void show() {        System.out.println("Father show...");    }    public void method() {        System.out.println("Father method...");    }}

方法重写

注解:@Override

要求:

  • 子类父类方法的名字返回值类型一摸一样

  • 父类私有(private)的方法子类无法访问,更无法重写

  • 子类重写父类方法时, 访问权限不低于父类
    private < 默认 (什么都不写)< protected < public

通常,只有局部变量private,父类一般都是public

public class NewPhone extends Phone{    //重写父类Phone#call()方法    //在打电话的时候, 增加播放彩铃功能.    @Override    public void call(String name) {        //调用父类的call()方法, 实现基础打电话功能.        super.call(name);                //加入新的需求: 播放彩铃        System.out.println("播放彩铃...");    }

多态

同一个事物在不同时刻表现出来的不同状态,形态–父类的多个子类形态


前提

  • 继承关系

  • 方法重写

  • 父类引用指向子类对象

Animal an = new Cat();

使用(左)父类的成员变量,(右)子类的成员方法

因为,方法重写了,但变量没有


但是new的父类对象无法调用子类没有重写的方法,所以使用向下转型

Cat c = (Cat)an;

Animal an = new Cat();        //编译看左 运行看右//父类变量--子类方法        an.eat();           //调用猫类中独有的 catchMouse()功能.        an.catchMouse();      //报错        //多态版的 猫类对象 ->  Cat类型的猫类对象(多态转普通对象)        Cat c = (Cat)an;          //引用类型的: 向下转型,     即: 大 -> 小.        c.catchMouse();   	//新的普通对象可以使用子类没有重写的方法

向上转型-向下转型

//向上转型 和 向下转型都是针对于 引用类型来讲的       // 向上转型:   cat() -> Animal()            Animal an = new Cat();          //类似于: 基本类型的隐式类型转换,  double d = 10;        //向下转型:   Animal()-cat() -> cat()             Cat c = (Cat)an;                //类似于: 引用类型的强制类型转换, 即:  int a = (int)d;

多态访问成员方法

开发常用

//cat重写animal的eatpublic static void show(Animal an) {            //Animal an = new Cat();     //编译看左Animal an, 运行看右cat.eat().    an.eat();} Cat c = new Cat();        show(c);            //猫吃鱼.        System.out.println("-------------------");

Instanceof

多态访问子类重写的成员方法的同时

用来识别归属子类,调用该子类独有的成员方法

public static void show(Animal an) {           //Animal an = new Dog();    an.eat();    //判断传入的是否是猫类    if (an instanceof Cat) {        //说明是猫类对象, 向下转型, 调用猫类方法        Cat c = (Cat)an;        c.catchMouse();    } else if(an instanceof Dog) {        //说明是狗类对象, 向下转型, 调用狗类方法        Dog d = (Dog)an;        d.lookHome();    }}

Final

锁死 类,变量,方法

  • 修饰类: 不能被继承, 但是可以继承其他类.

  • 修饰变量: 是个常量(Int类), 只能被赋值一次.

    final int a = 10;//a = 20;       //这样写会报错.
    
  • 修饰方法: 不能被子类重写.

面试题

  • final修饰**基本类型的常量(final int a = 10)和 修饰引用类型的数据(final Father f = new Father() )**有什么区别?
final int a = 10;//a = 20;       //这样写会报错.//如果修饰的引用类型的常量:	//是地址值不能发生变化		//但是该对象的属性值可以发生变化.final Father f = new Father();//f = new Father();           //这样写会报错, 如果修饰的引用类型的常量: 是地址值不能发生变化,f.name = "刘亦菲";f.name = "高圆圆";System.out.println(f.name);

  • final-finally-finalize 三个关键字的区别

Static

表示静态的意思, 可以修饰成员变量, 成员方法

作用(特点):

  • 随着类的加载而加载.

  • 优先于对象存在.

  • 被static修饰的内容, 能被该类下所有的对象所共享.

  • 静态内容可以被 类名. 的形式直接调用.

    Student.show2(); 
    

静态方法访问特点

访问特点:
静态方法只能访问静态的成员变量和静态的成员方法.
即: 静态只能访问静态
注意事项:
1.在静态方法中, 是没有this, super关键字的.
2.因为静态的内容是随着类的加载而加载, 而this和super是随着对象的创建而存在.
即: 先进内存的, 不能访问后进内存的.

        Student s = new Student();        s.show1();         s.show2();   // 不报错, 不推荐.	//结论: 非静态方法可以访问所有成员(非静态变量和方法, 静态变量和方法)        Student.show2();    	//静态方法只能访问静态成员

public class Student {    String name = "刘亦菲";        //非静态成员变量    static int age = 33;           //静态的成员变量    public void show1() {    }    public static void show2() {        System.out.println("show2方法  静态方法");    }}

抽象类

特点

  • 抽象类和抽象方法都用 **abstract ** 修饰

  • 抽象方法没有方法体,用abstract修饰

    //抽象方法public abstract void eat();
    
  • 有抽象方法的类一定是抽象类

    //父类, 动物类public abstract class Animal {    //1.类中有一个抽象方法eat(), 还有一个非抽象方法sleep().    public abstract void eat();    public void sleep() {        System.out.println("动物要睡!");    }}
    
  • 创建抽象类多态, 来完成抽象类的初始化.

    Animal an = new Cat();
    
  • 普通类继承抽象类 必须重写父类所有的抽象方法.

    public class Cat extends Animal{        @Override        public void eat() {                System.out.println("猫吃鱼!");       }}
    
  • 抽象类继承抽象类, 不用重写父类的抽象方法.

  • 小技巧: final 一般要结合 static, public, 或者private 一起使用.

    static final String COUNTRY = "中国";     //国籍
    

  • 思考: 既然抽象类不能实例化, 那要构造方法有什么用?
    答: 用于子类对象访问父类数据前, 对父类数据进行初始化

    ​ 也就是:可以使用抽象类多态初始化父类变量和方法

Person p = new Student();
  • 思考: 抽象类中的抽象方法和非抽象方法的作用是什么?
    抽象方法: 强制子类完成某些事情(作为模板重写
    非抽象方法: 让子类可以直接使用

接口

特点

  • 接口用 interface 修饰.

  • 类和接口之间是实现关系, 用**implements(实现)**关键字表示.

  • 接口不能实例化.
    那接口如何实例化呢?
    可以通过多态的方式, 创建其子类对象, 来完成接口的实例化. 这也叫: 接口多态

    Jumpping jp = new Cat();
    
  • 接口的子类:
    1.如果是普通类, 则必须重写父接口中所有的抽象方法.
    2.如果是抽象类, 则可以不用重写父接口中的抽象方法.


  • 接口中有且只能有常量或者抽象方法.
    变量的默认修饰符: public static final
    方法的默认修饰符: public abstract

  • 接口中是没有构造方法的, 因为它主要是用来对类的功能进行: 扩展, 升级, 延伸.-----也就是,扩展定义成员方法的模板

    //定义接口, 扩展说英语的功能public interface SpeakEnglish {    void speak();}
    
  • JDK1.8的时候, 接口中加入了两个新成员:
    支持静态方法
    支持默认方法, 必须用default修饰.


面试

抽象类和接口的区别

  • 成员

    • 抽象类 :变量 ,常量,构造方法,抽象方法,非抽象方法
    • 接口:常量,抽象方法,JDK.8的静态方法,默认方法
  • 关系

    • 类与类间:只能多层单个继承

    • 类与接口间:一个类可在继承一个类的同时可实现一个或多个接口

      //           子类 继承    一个亲爹 实现       多个干爹public class Cat extends Animal implements A,B,C{}
      
    • 接口与接口间:一或多

      public interface B extends C{    public abstract void methodB();}
      
  • 设计理念

    • 抽象类:定义功能模板
    • 接口:扩展功能模板

对类进行分类管理,按照功能或模块划分

注意

  • java.lang 包下的类可以直接使用, 无需导入

  • 用public修饰的类叫: 公共类, 也叫顶级类, 在一个.java文件中, 顶级类只能有一个, 且必须和文件名一致

  • 不导包创建对象

//创建Scanner对象java.util.Scanner sc = new java.util.Scanner(System.in);//创建 demo11包下的 PingPangPlayer类的对象呢?com.itheima.demo11_coach.PingPangPlayer p1 = new com.itheima.demo11_coach.PingPangPlayer("王励勤", 33);p1.eat();

  • 导包
import com.itheima.demo11_coach.PingPangPlayer;import java.util.Scanner;//psvmScanner sc = new Scanner(System.in);PingPangPlayer p1 = new PingPangPlayer("王励勤", 33);p1.eat();

权限修饰符

修饰类, 成员变量, 构造方法, 成员方法, 不同的权限修饰符对应的功能不同

publicprotected默认private
同一个类中
同一个包中的子类或者其他类
不同包中的子类
不同包中的其他类(无关类)

记忆

  • 访问权限修饰符的权限从大到小分别是:

    public > protected > 默认 > private

  • 在实际开发中, 如果没有特殊需求, 则成员变量都用private修饰, 其他都用public修饰.

  • 大白话总结四个访问权限修饰符的作用:
    private: 强调的是给 类自己 使用.
    默认: 强调的是给 同包下的类 使用.
    protected: 强调的是给 子类 使用.
    public: 强调的是给 大家 使用.


Tostring

重写object类的tostring()方法(自动生成),打印该对象的各个属性值

不写的话默认打印地址值

public String toString(){return "cat{" +				"name" + name + '\\'			'}'}

常用方法

Scanner

产生原因:
1. nextInt()方法的结束标记是: \r\n, 但是该方法只接收整数, 不接收\r\n.
2. nextLine()方法的结束标记是: \r\n, 识别到上边遗留下来的\r\n后, 直接结束了.

解决方案:
1. 采用next()方法解决.
2. 重新调用一次nextLine();
3. 重新new一个Scanner.
4. 实际开发写法: 目前超纲, 先了解.
都用字符串接收, 然后把字符串类型的数字, 转成对应的 int类型的数字即可.

开发中写法

  //1. 创建对象.
        Scanner sc = new Scanner(System.in);
        //2. 提示用户录入
        System.out.println("请录入一个整数");
        //3. 接收并输出: 整数
        String s1 = sc.nextLine();
        //核心(超纲): 把字符串数字转成int数字
        int num = Integer.parseInt(s1);
        System.out.println(num + 3);

        //4. 接收并输出: 字符串
        System.out.println("请录入一个字符串: ");
        String s2 = sc.nextLine();
        System.out.println(s2);

Object类

Object类是所有类的父类, 所有的类都直接或者间接继承自Object类.

public class abc (extends object){			}

toString()

  1. Object类自带的toString()默认打印的是对象的地址值, 无意义, 子类一般都会重写该方法.
  2. 输出语句直接打印对象, 默认调用了对象的 toString()方法.

equals()

Object类自带的equals()方法, 默认比较的是两个对象的地址值是否相同, 无意义,
子类一般都会重写该方法, 改为比较对象的各个属性值.

  1. 实际开发中, 我们认为, 如果同一个类型的两个对象, 各个属性值都相同, 那么它们就是同一个对象.
      //false,  比较地址值.
System.out.println(s1.equals(s2));     
@Override
public boolean equals(Object o) {       //s1.equals(s2)
    /*
        s1: this
        s2: o     student
     */
    //1. 提高效率, 有可能要比较的两个对象是同一个类型的对象.
    if (this == o) return true;

    //2. 提高健壮性, 有可能要比较的两个对象不是同一个类型的对象.
    if (o == null || this.getClass() != o.getClass()) return false;

    //3. 向下转型
    Student student = (Student) o;
    //4. 比较两个对象的年龄是否相同.
    if (this.age != student.age) return false;
    //5. 比较两个对象的姓名是否相同.
    //这里的equals()指的是:   String类中的equals()方法
    return this.name != null ? this.name.equals(student.name) : student.name == null;
}

String类

String创建对象内存图解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kWAbOZ1N-1648090035451)(D:\360MoveData\Users\Asus\Desktop\image-20210916094712904.png)]

通过new创建的字符串对象, 每一次new都会申请一个内存堆空间, 虽然内容相同, 但是地址值不同.

   char[] chs = {'a', 'b', 'c'};
 String s1 = new String(chs);
        String s2 = new String(chs);
**//这里的s1和s2的地址值肯定是不同的.**

通过""方式创建的字符串, 只要字符序列相同(顺序和大小写), 无论在程序代码中出现几次**, JVM都只会创建一个String对象, 并在字符串池中维护.**

    String s1 = "abc";
String s2 = "abc";	**//这两个对象在内存中其实是同一个对象.** 

char[] ==> string

演示 public String(char[] chs); 把接收到的字符数组, 转成其对应的字符串形式.

普通写法
char[] chs = {'h', 'e', '黑','马','程','序','员', 'l', 'l', 'o'};
String s3 = new String(chs);
System.out.println("s3: " + s3);
System.out.println("-------------------");
实际开发写法
String s7 = "abc";      //语法糖.
System.out.println("s7: " + s7);

字符串的比较

​ String类中的方法

        public boolean equals(Object obj);              比较两个字符串是否相等, 比较的是内容,  区分大小写.        public boolean equalsIgnoreCase(String s);      比较两个字符串是否相等, 比较的是内容,  不区分大小写.
equals()
System.out.println(s1 == s2);           //falseSystem.out.println("-------------------");//5.通过equals()分别判断s1和s2, s1和s3, s3和s4是否相同.System.out.println(s1.equals(s3));      //trueSystem.out.println(s3.equals(s4));      //falseSystem.out.println("-------------------");
equalsIgnoreCase()
//6.通过equalsIgnoreCase()判断字符串abc和ABC是否相同.System.out.println(s3.equalsIgnoreCase("ABC"));   

字符串拼接

Java中针对于常量是有优化机制的:

针对于byte类型:

​ 如果是常量相加: 会直接运算, 然后看结果在不在左边的数据类型范围内, 在不报错, 不在就报错.
​ 如果是变量相加: 会提升类型, 然后运算, 提升规则: byte, short, char -> int -> long -> float -> double

针对于String类型:

​ 如果是常量拼接: 会直接拼接, 不会在(堆区)开辟新空间.
​ 如果是变量拼接: 会在堆区开辟新空间.

String s1 = "ab";String s2 = "c";String s3 = "abc";//底层代码,会自动new一个string对象,开辟新的内存空间//System.out.println(s3 == (new StringBuilder()).append(s1).append(s2).toString());//System.out.println(s3 == (new StringBuilder()).append("ab").append(s2).toString());System.out.println(s3 == s1 + s2);          //falseSystem.out.println(s3 == "ab" + s2);        //falseSystem.out.println(s3 == "ab" + "c");       //true

//案例: 演示遍历字符串.
/*
涉及到的String类中的方法:
public int length(); 获取字符串的长度
public char charAt(int index) 根据索引, 获取其对应的字符.

小细节:
字符串的底层其实就是一个字符数组, 所以字符串中每个元素都是由编号的, 编号是从0开始的.


String类中的方法:
public int length(); 获取字符串的长度
public char charAt(int index) 根据索引, 获取其对应的字符.

for (int i = 0; i < s.length(); i++) {    //i就是字符串中, 每个字符的索引    //4. 根据索引, 获取到字符串中的每一个字符.    char ch = s.charAt(i);    //5. 打印结果.    System.out.println(ch);}

if (ch >= 'A' && ch <= 'Z') {    //大写字母字符
if(ch >= 'a' && ch <= 'z') {    //小写字母字符
if(ch >= '0' && ch <= '9') {    //数字字符

public String concat(String str);       拼接字符串, 返回新串.
String s3 = s1 + s2;        //s3 = "abc", 会开辟空间(堆)String s4 = s1.concat(s2);  //s4 = "abc", 不会开辟堆空间.

字符串反转

    for (int i = s.length() - 1; i >= 0; i--) {            //方法一:stringbuilder.append()                    sb.append(s.charAt(i));  }                        return sb.toString();//            //方法三:string.concat()//                     newStr= newStr.concat(String.valueOf(s.charAt(i)));      }//                            return newStr;//            //方法三:string.charAt()//                   newStr += s.charAt(i) ;       }//                                return newStr;            方法四;object.reverse()//        }     StringBuilder aaa=new StringBuilder();//              aaa.append(s);//              StringBuilder newStr1=aaa.reverse();//            return newStr1.toString();

StringBuilder

StringBuilder叫: 字符串缓冲区类, 有自带的缓冲区, 可以理解为它是容器,
里边存储的内容是可变的.


StringBuilder中的构造方法:
public StringBuilder(); 空参构造, 创建StringBuilder对象.
public StringBuilder(String str); 带参构造, 创建StringBuilder对象.
可以理解为把 String对象 -> StringBuilder对象.


涉及到的StringBuilder中的方法:

​ public StringBuilder append(任意类型);

append不会覆盖,append后地址值不变,常量不会开辟新的内存空间

sb.append("黑马程序员").append("夯哥");        for (int i = 0; i < arr.length; i++)            sb.append(arr[i]).append(i == arr.length - 1 ? "]" : ", ");        return sb.toString();

添加任意类型的数据, 返回StringBuilder本身.

StringBuilder对象反转

​ public StringBuilder reverse(); 反转StringBuilder对象, 返回StringBuilder本身.

StringBuilder sb3 = sb2.reverse();
String reverseStr = new StringBuilder(str).reverse().toString();System.out.println(reverseStr);
System.out.println(reverse(str));System.out.println("------------------------");

String对象 -> StringBuilder对象
public StringBuilder(String str); 带参构造, 创建StringBuilder对象.

String s2 = "传智播客";StringBuilder sb2 = new StringBuilder(s2);      //String对象  ->  StringBuilder对象System.out.println("sb2: " + sb2);

StringBuilder对象 -> String对象
StringBuilder类中的toString()方法
public String toString();

​ 返回该对象的字符串形式.

StringBuilder sb = new StringBuilder();sb.append("hello");String s1 = sb.toString();    

排序

冒泡排序

//1. 定义数组, 记录要排序的元素.int[] arr = {25, 69, 80, 57, 13};//2. 通过外循环, 控制比较的轮数.//这里的-1是为了啥?  为了提高效率.for (int i = 0; i < arr.length - 1; i++) {//0, 1, 2, 3    //3. 通过内循环, 控制每轮比较的次数.    /*        这里的-1是为了啥?   为了防止出现索引越界异常.        这里的-i是为了啥?   为了提高效率.     */    for (int j = 0; j < arr.length - 1 - i; j++) {       //4, 3, 2, 1        //4. 如果前一个元素比后一个元素大, 就交还它们的位置.        //即: arr[j] 和 arr[j + 1] 比较        if (arr[j] > arr[j + 1]) {            int temp = arr[j];            arr[j] = arr[j + 1];            arr[j + 1] = temp;        }    }}//5. for循环执行结束后, 已经排好序了, 我们直接打印数组即可.            System.out.println("排序后: " + Arrays.toString(a));

Arrays工具类

工具类介绍:
1. 构造方法私有化.
2. 成员都是静态的, 可以通过 类名. 的形式直接调用.

Arrays类中的成员方法:
public static String toString(int[] arr) 把数组转成其对应的字符串形式, 例如: [1, 3, 5, 6]
public static void sort(int[] arr) 对数组元素进行升序排序.

int[] arr = {25, 69, 80, 57, 13};//补充: 打印排序前的结果Arrays.sort(arr);//3.打印排序后的结果.System.out.println("排序后: " + Arrays.toString(arr));

Integer工具类

public Integer(int value);int类型的数据封装成Integer类型的对象,public Integer(String value);String类型的数据封装成Integer类型的对象, 注意: 必须是纯数字类型的字符串.

int -> String

//方式一: 直接在数值后边拼接 "",        推荐使用.int a = 10;String s1 = a + "";System.out.println("s1: " + s1);//方式二: String#valueOf()String s2 = String.valueOf(111);System.out.println("s2: " + s2);System.out.println("-----------------------------");

String -> int

//方式1: 转换思路 String -> Integer -> intString s3 = "123";//String -> IntegerInteger i1 = new Integer(s3);//Integer -> intint num1 = i1.intValue();System.out.println("num1: " + num1);//方式2: 通过Integer#parseInt();方法实现,  推荐使用.int num2 = Integer.parseInt(s3);System.out.println("num2: " + num2);

//String  ->     intint num = Integer.parseInt("123");//String  ->     doubledouble d = Double.parseDouble("10.3");//String  ->     booleanboolean flag = Boolean.parseBoolean("false");System.out.println("num: " + num);System.out.println("d: " + d);System.out.println("flag: " + flag);System.out.println("-------------------------------");//2. 演示 字符   -> 字符串之间相互转换, 略.//char   ->     StringString s1 = 'a' + "";//String  ->     charchar ch = "abc".charAt(1);//3. 演示 字符数组   -> 字符串之间相互转换,//String      ->      char[]String str = "黑马程序员";char[] chs = str.toCharArray();//System.out.println(chs);    //这里不是地址值,而是数组元素.  IO流解释.for (int i = 0; i < chs.length; i++) {    char c = chs[i];    System.out.println(c);}// char[]      ->      StringString str2 = new String(chs);System.out.println("str2: " + str2);

/需求1: 演示自动装箱.//1. 不采用自动装箱int a = 10;Integer i1 = new Integer(a);System.out.println(a);System.out.println(i1);//2. 自动装箱.Integer i2 = a;System.out.println(i2);System.out.println("------------------------");//需求2: 演示自动拆箱//3. 不采用自动拆箱.int b = i1.intValue();System.out.println(b);//4. 采用自动拆箱.int c = i1;System.out.println(c);

Split

//1. 定义变量, 记录要操作的字符串.String s = "91 27 45 38 50";System.out.println(s);//2. 把字符串转成其对应的字符串数组.String[] strArray = s.split(" ");

Date

//1. 演示 public Date();          采用当前系统默认时间, 生成Date对象.Date d1 = new Date();

//2. 演示 public Date(long time); 采用指定的毫秒值, 生成对应的Date对象.//Java中采用的时间原点是: 1970年1月1日 00:00:00Date d2 = new Date(0L);

获取上述时间对应的毫秒值.System.out.println(d1.getTime());
 采用指定的毫秒值, 生成Date对象.//Date d2 = new Date(1590984453616L);Date d2 = new Date();d2.setTime(1590984453616L);System.out.println(d2);
date2String
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");//SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");//2.2 按照指定的模板进行格式化操作.String result = sdf.format(d1);
string2Date
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");//2.2 调用SimpleDateFormat#parse()方法, 完成解析操作.Date date = sdf.parse(s);

Calendar

Calendar类中的成员变量:    public static final int YEAR                    表示年份.    public static final int MONTH                   表示月份.    public static final int DAY_OF_YEAR             表示年中的某一天.    public static final int DAY_OF_MONTH            表示月中的某一天.    public static final int DAY_OF_WEEK             表示星期中的某一天.Calendar类中的成员方法:    public static Calendar getInstance();           获取Calendar的子类对象.    public int get(int field);                      根据给定的日历字段, 获取其对应的值.    public void set(int year, int month, int day)   设置时间为指定的年,,.    public void add(int field, int count);          设置指定的日历字段, 偏移指定的量.

内部类

内部类分为成员内部类和局部内部类.
成员内部类: 一般多用于框架, 是用来对类的功能进行增强的.
局部内部类: 这个是我们常用的类型,

Person p = new Person() {  
    
    @Override    
    public void eat() {       
        System.out.println("人要吃饭"); 
    }  
    
    @Override    
    public void sleep() {        System.out.println("人要睡觉"); 
                        }  
    
    @Override    
    public void study() {        System.out.println("人要学习");    
                        }};
p.eat();
p.sleep();
p.study();

匿名内部类

概述:
匿名内部类就是没有名字的 局部内部类.
局部位置: 方法中, 或者方法的形参列表.
格式:
new 类名或者接口名() {
//重写类或者接口中所有的抽象方法.
};
本质:
匿名内部类就是一个继承了类或者实现了接口的匿名的子类对象.

使用场景:    1. 当对对象方法(也叫: 成员方法)仅调用一次的时候.    2. 匿名内部类可以作为方法的实参进行传递.小技巧:    当抽象类或者接口中的抽象方法不超过3个的时候(一般是只有1), 就可以考虑使用匿名内部类.
Animal.show(new Animal(){      //实际开发经常这样写.    @Override    public void eat() {        System.out.println("匿名内部类创建Animal对象, 重写eat()方法");    }});

IO流

异常

异常简介:
概述:
Java中的异常指的是程序出现不正常的情况.
分类:
Throwable 类, 异常的最顶层类, 所有的异常都是它儿子.
Error: 表示错误, 例如: 服务器宕机, 数据库崩溃, 这些异常一般和我们的代码没关系, 也不需要我们(程序员)处理.
Exception: 表示异常, 这个才是我们常说的异常.
编译期异常: 发生在编译期间的异常, 不处理, 程序编译通不过.
非RuntimeException及其子类, 都叫: 编译期异常.

​ 运行时异常: 发生在运行期间的异常, 不处理, 程序也能通过编译.
​ 指的是RuntimeException及其子类.

JVM默认处理异常的方式:
采用"抛出异常(即: throws)的方式实现, 会将异常的类型, 异常的描述信息, 以及异常出现的位置打印到控制台上.
并终止程序的运行.

try.catch.finally

语句

​ 格式:

        try{
            //可能出问题的代码
        } catch(Exception e) {
            //走这里, 说明程序出现异常了, 所以这里写的基本上都是解决方案.
            e.printStackTrace();        //该方法会将异常的类型, 描述信息及位置打印到控制台上.
        } finally {
            //这里的代码正常情况下永远都会执行, 一般是用来释放资源的.
        }

​ 特点:
​ 处理完之后, 代码会继续往下执行.

没有return,后面代码都继续跑

**有return,不写finally,就不会运行finally后面代码

声明抛出异常****

• 格式

*throws* 异常的类型; //该内容是写到方法的形参列表之前的.

特点: 处理完后, 程序会终止执行.

file

构造方法(new)

public File(String pathName);                   根据传入的路径, 获取对应的File对象.
public File(String parent, String child);       根据传入的父目录和子文件名获取其对应的File对象.
public File(File parent, String child);         根据传入的父目录对象和子文件名获取其对应的File对象.


成员方法 .

public boolean createNewFile();     创建空文件, 文件不存在就创建返回true, 存在就不创建, 返回false.
public boolean mkdir();             创建单级文件夹, 其实是: make directory单词的缩写.
public boolean mkdirs();            创建多级文件夹.

File类的判断功能:

public boolean exists();            //判断指定的文件(夹)是否存在.
public boolean isFile();            //判断给定的路径是否是文件, 默认包含了exists()方法的功能.
public boolean isDirectory();       //判断给定的路径是否是文件夹, 默认包含了exists()方法的功能.

File类的获取功能:

    public String getAbsolutePath();    //获取绝对路径.
    public String getPath();            //创建对象的时候用什么路径, 就获取什么路径, 一般是用于获取相对路径.
    public String getName();            //获取文件(夹)的名字.
    public String[] list();             //获取指定的目录下所有的 文件(夹) 的字符串数组形式.
    public File[] listFiles();          //获取指定的目录下所有的 文件(夹) 的File对象数组形式.

删除功能

 public boolean delete();        删除文件或者文件夹.

​ 两个小细节:
​ 1. 如果是删除文件夹, 则该文件夹必须为空文件夹.
​ 2. Java中的删除不走回收站.

字节流

输出流

FileOutputStream: 普通的字节输出流, 以字节为单位, 往文件中写数据.
构造方法:

        public FileOutputStream(String path);            接收字符串形式的路径
        public FileOutputStream(File path);              接收File对象形式的路径.
        public FileOutputStream(String path, boolean append);   如果传true, 表示往文件中追加数据, false: 覆盖.
        public FileOutputStream(File path, boolean append);     如果传true, 表示往文件中追加数据, false: 覆盖.

成员方法:

        public void write(int b);       一次写一个字节
        public void write(byte[] bys);  一次写一个字节数组
        public void write(byte[] bys, int start, int len);  一次写一个字节数组的一部分
        public void close();        关闭流.

String类中有一个**getBytes()**方法, 可以把字符串转成其对应的字节数组形式.

fos.write("hello".getBytes());//换行符fos.write("\r\n".getBytes());  //window操作系统: \r\n,  linux: \n   mac: \r

获取字节数组(字节码)

System.out.println(Arrays.toString("静安寺".getBytes()));

GC回收机制

注释 ctrl +/

ctrl +shift +/

/**+enter

输入流

字节输入流 一次读取一个字节数组.
/*
FileInputStream: 普通的字节输入流, 以字节为单位读取数据.

​ 构造方法:
​ public FileInputStream(String path);
​ public FileInputStream(File path);

​ 成员方法:
​ public int read(); 一次读一个字节, 并返回读取到的该字节的ASCII码值, 读不到返回-1
​ public int read(byte[] bys); 一次读一个字节数组, 并返回读取到的有效字节数,
​ 并将读取到的数据封装到字节数组中, 读不到返回-1
​ public void close();

(len = fis.read(bys)) != -1  这行代码做了3件事    1. 执行fis.read(bys),         一次读取一个字节数组, 并把读取到的内容存储到bys数组中.    2. 执行len = fis.read(bys)    将读取到的有效字节数赋值给变量len    3. 执行len != -1              如果len不等于-1, 说明读到内容了, 进循环.

java字典read

read(byte[] b)         throws IOException

读取 b.length字节的数据从这个输入流到一个字节数组。这种方法块直到一些输入是可用的。

普通字节流

FileInputStream fis = new FileInputStream("day12/data/1.txt");//2. 创建输出流对象, 关联目的地文件.FileOutputStream fos = new FileOutputStream("day12/data/2.txt");

高效缓冲字节流

BufferedInputStream bis = new BufferedInputStream( new FileInputStream("day12/data/1.avi"));//2. 创建输出流对象, 关联目的地文件.BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("day12/data/5.avi"));

字符流

普通字符流

FileReader fr = new FileReader("day12/data/1.txt");     //只能用默认码表读.//2. 创建输出流对象, 关联目的地文件.FileWriter fw = new FileWriter("day12/data/2.txt");     //只能用默认码表写.

高效字符流

BufferedReader br = new BufferedReader(new FileReader("day12/data/1.txt"));//2. 创建输出流对象, 关联目的地文件.BufferedWriter bw = new BufferedWriter(new FileWriter("day12/data/2.txt"));

按行读写

//3. 定义变量, 记录读取到的内容或者有效字节(符)数.String line = null;//4. 循环读取,只要条件满足就一直读, 并将读取到的内容赋值给变量.while ((line = br.readLine()) != null) {    //5. 将读取到的内容写入到目的地文件中.    //System.out.println(line);    bw.write(line);    //小细节, 千万别忘记加 换行    bw.newLine();}//6. 关流, 释放资源.br.close();bw.close();

字符转换流

这里不传码表, 就用默认码表(utf-8)—可省略

InputStreamReader isr = new InputStreamReader(new FileInputStream("day12/data/1.txt"),"utf-8");   //这里不传码表, 就用默认码表(utf-8)//2. 创建输出流对象, 关联目的地文件.OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day12/data/2.txt"));      //因为使用默认码表, 所以码表名省略了. 

序列化流

对象中的某个属性的值不想被序列化, 该如何实现?
给该成员变量加一个修饰符: transient.

transient: 被它修饰的成员变量不参与序列化操作.

//1. 创建序列化流, 封装目的地文件.ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("../day12/data/1.txt"));//2. 创建JavaBean对象.Student s = new Student("刘亦菲", 33);//3. 进行序列化操作.oos.writeObject(s);

反序列化流

如果有变量不想被序列化

private transient int age;  
反序列化操作. //1. 创建序列化流, 封装数据源文件. ObjectInputStream ois = new ObjectInputStream(new FileInputStream("../day12/data/1.txt")); //2. 进行反序列化操作.Student s = (Student)(ois.readObject());//3. 打印对象. System.out.println(s); //4. 关流. ois.close();

运行时间

long start = System.currentTimeMillis();//1.分别通过四种方式拷贝视频文件, 并观察它们的效率.//2.通过普通的字节流一次读写一个字节的形式实现.//method01();                   138550毫秒//3.通过普通的字节流一次读写一个字节数组的形式实现.//method02();                     //70毫秒long end = System.currentTimeMillis();System.out.println("拷贝时间为: " + (end - start));
Commons简化包
FileUtils.copyDirectoryToDirectory(new File("d:/Compile"), new File("d:/dest"));
FileUtils.copyFile(new File("day12/data/1.txt"), new File("day12/data/2.txt"));

按行读写

//3. 定义变量, 记录读取到的内容或者有效字节(符)数.String line = null;//4. 循环读取,只要条件满足就一直读, 并将读取到的内容赋值给变量.while ((line = br.readLine()) != null) {    //5. 将读取到的内容写入到目的地文件中.    //System.out.println(line);    bw.write(line);    //小细节, 千万别忘记加 换行    bw.newLine();}//6. 关流, 释放资源.br.close();bw.close();

字符转换流

这里不传码表, 就用默认码表(utf-8)—可省略

InputStreamReader isr = new InputStreamReader(new FileInputStream("day12/data/1.txt"),"utf-8");   //这里不传码表, 就用默认码表(utf-8)//2. 创建输出流对象, 关联目的地文件.OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day12/data/2.txt"));      //因为使用默认码表, 所以码表名省略了. 

序列化流

对象中的某个属性的值不想被序列化, 该如何实现?
给该成员变量加一个修饰符: transient.

transient: 被它修饰的成员变量不参与序列化操作.

//1. 创建序列化流, 封装目的地文件.ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("../day12/data/1.txt"));//2. 创建JavaBean对象.Student s = new Student("刘亦菲", 33);//3. 进行序列化操作.oos.writeObject(s);

反序列化流

如果有变量不想被序列化

private transient int age;  
反序列化操作. //1. 创建序列化流, 封装数据源文件. ObjectInputStream ois = new ObjectInputStream(new FileInputStream("../day12/data/1.txt")); //2. 进行反序列化操作.Student s = (Student)(ois.readObject());//3. 打印对象. System.out.println(s); //4. 关流. ois.close();

运行时间

long start = System.currentTimeMillis();//1.分别通过四种方式拷贝视频文件, 并观察它们的效率.//2.通过普通的字节流一次读写一个字节的形式实现.//method01();                   138550毫秒//3.通过普通的字节流一次读写一个字节数组的形式实现.//method02();                     //70毫秒long end = System.currentTimeMillis();System.out.println("拷贝时间为: " + (end - start));
Commons简化包
FileUtils.copyDirectoryToDirectory(new File("d:/Compile"), new File("d:/dest"));
FileUtils.copyFile(new File("day12/data/1.txt"), new File("day12/data/2.txt"));
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值