学习方法
先只通过代码写注释,再只通过注释写代码
先解决问题,再发现更多方案,最后选择最优
计算机基础
快捷键
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 = 10;
int a  =  (int)d;
 
常量相加,直接运算,结果不能超过数据类型范围
byte b1 = 3;
byte b2 = 4;
byte 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循环
固定循环次数
for(int 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();
 
权限修饰符
修饰类, 成员变量, 构造方法, 成员方法, 不同的权限修饰符对应的功能不同
| public | protected | 默认 | 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()
- Object类自带的toString()默认打印的是对象的地址值, 无意义, 子类一般都会重写该方法.
 - 输出语句直接打印对象, 默认调用了对象的 toString()方法.
 
equals()
Object类自带的equals()方法, 默认比较的是两个对象的地址值是否相同, 无意义,
 子类一般都会重写该方法, 改为比较对象的各个属性值.
- 实际开发中, 我们认为, 如果同一个类型的两个对象, 各个属性值都相同, 那么它们就是同一个对象.
 
      //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"));









