Java学习---第五周总结

1. 多态(重点)

1.1 什么是多态

现实世界事物描述:一个事物体现出的的不同形态! (主要体现在内存中)
	例: 水这个事物,有: 液态,固态,气态

1.2 多态的前提条件

1)必须存在继承关系, 如果没有继承,谈不了多态! (继承的好处第三点)

2)必须存在方法重写,需要让子类完成自己的业务功能,需要将父类的某些功能进行覆盖(重写)
    举例:动物都需要吃
 	只有见到具体动物---才知道吃什么,具体的动物的子类将"吃"的功能进行重写
3)需要存在"父类引用指向子类对象"
      格式:  Fu fu =new Zi() ;
      父类名 对象名 = new 子类名() ;   "向上转型"(使用的是父类的东西)

1.3 多态中的成员访问特点

1.3.1 格式
父类名 对象名 = new 子类名();
	即Fu fu = new Zi();(向上转型,使用的是父类的东西)
1.3.2 访问成员
  1.  1) 成员变量:
        编译看左,运行看左! (如果编译通过了,说明Fu中存在变量,运行看左,使用父类的东西)
     2) 成员方法(非静态):
        编译看左,运行看右.使用子类重写后的方法(因为子类出现了父类一模一样的方法声明,覆盖了)
     3) 静态的成员方法:
        算不上方法重写.和类相关的.称为"类成员"    
        编译看左,运行看左!
        随着类的加载而加载,访问通过类名访问(推荐)
     4) 构造方法:
        因为存在继承关系,存在无参构造/有参构造,都需要父类先初始化,然后才是子类,分层初始化.
    

    例:

//父类
class Fu{
    int num = 10 ;
    //成员方法(非静态)
    public void show(){
        System.out.println("show Fu") ;
    }
    // 静态方法
    public static void method(){
        System.out.println("method Fu...");
    }
    //无参构造
    public Fu(){
        System.out.println("Fu...");
    }
}
// 子类
class Zi extends  Fu{
    int num = 20 ;
    //重写了
    @Override
    public void show() {
        System.out.println("show Zi") ;
    }

    public static void method(){
        System.out.println("method Zi...");
    }
    public Zi(){
        System.out.println("Zi");
    }
}
public class DuoTaiDemo {
    public static void main(String[] args) {
        //需要存在"父类引用指向子类对象"
        Fu fu  = new Zi() ; //父类的引用fu---堆内存中创建的它的子类对象
        //访问成员变量
        System.out.println(fu.num) ;
        fu.show() ;

       // fu.method() ;
        
       //静态方法推荐类名访问方式:
      /*  Fu.method() ;
        Zi.method();*/
    }
}

1.4 多态的好处

1)可以提高代码的复用性(继承保证的)
2)可以提高代码的扩展性(由多态的保证:Fu fu = new Zi() 父类引用指向子类对象)

1.5 多态的弊端

多态的弊端:
      格式:Fu fu = new Zi()  :向上转型 (使用的是父类的东西)
           不能访问子类的特有功能
现在就需要访问子类的特有功能:如何解决:
      1)直接创建具体的子类: 子类new 子类
         从内存角度考虑: 需要在堆内存中继续开辟空间,消耗内存空间
      2)优化内存:
         父类引用指向子类对象, 向下转型
 	格式:
      Zi zi = (Zi)fu; 引用类型了
 
1.5.1 向下转型使用不当,出现异常
多态的在使用过程中,存在向上转型和向下转型,
向下转型使用不当,会出现问题:
  java.lang.ClassCastException:类转换异常:
  属于 "运行时期异常"----->代码不严谨导致的
      例 :"狗是动物"向下转为"狗是狗",
		但是不可以再向下转型为 "猫是狗"

2. 抽象

2.1 抽象的定义

在现实事物中,将比较概括性的事物统称为"抽象的事物".
例: 
猫和狗是具体的动物了,他们都继承自动物类,将动物就可以看成是一个抽象的事物;
猫和狗具体的功能应该具体体现,在动物事物中,应该给出一个声明即可,不需要具体体现!

2.2 抽象类的格式

abstract class 类名{}

2.3 抽象类的注意事项

1)在一个类中,如果当前类中存在抽象功能(方法),那么这个类必须抽象类;

2)一个抽象类中,不一定都都是抽象方法;
	抽象方法:没有方法体的一个成员方法,并且携带一个关键字 abstract
 权限修饰符 abstract 返回值类型  方法名(形式参数列表) ;
 
3)抽象类的子类:
	为抽象类: 定会存在具体的子类,否则没有意义!
	为具体类:它才有意义,可以创建实例!继承的抽象方法,必须重写.
	
4)抽象类的本质:
	强制子类必须完成的事情!

2.4 抽象类的特点

不能实例化 (不能创建对象),即不能new对象,必须通过具体子类向上转型实现.
2.4.1 重写类的成员特点
成员变量:
       既可以是变量,也可以是常量!
成员方法:
       既可以是抽象方法,也可以是非抽象方法
构造方法:
       存在无参/有参:分层初始化
       目的:对数据进行初始化!

2.5 abstract 关键字和那些关键字冲突

 private:
 	被private修饰的方法只能在本类访问, 有一个abstract关键字:强制子类重写.
final:
	被final修饰的成员方法,不能被重写,而abstract强制子类重写
static:
	被static修饰符的方法,需要被类名访问,随着类的加载而加载,而abstract需要让子类重写这个方法,通过对象名来访问(访问时机冲突)
	
方法重写的注意事项
	子类继承父类:  重写父类的方法的时候,访问权限不能更低,跟父类的权限保持一致,否则报错!

2.6 抽象类面试题

例 : 一个类如果没有抽象方法,那么将这个类定义为抽象类有什么意义呢?

意义:
    就是为了不让外界new对象:不能实例化 抽象类特点:不能实例化 (如何实例化,通过抽象类多态实例化:具体的子类)

  这个类没有抽象方法,将它定义为抽象类:

  举例:
        后面的日历类Calendar(特殊的常用类之抽象类) 还有很多jdk提供的

        里面会存在一些静态功能:返回值是它自己本身

        public static Calendar getInstance()

3. 接口(重点)

3.1 什么是接口

接口实际就是描述事物本身之外的"额外功能(扩展功能)"
开发核心宗旨:面向接口编程

举例:

狗会站着走路, 这就是被训练出来的它本身不具备的额外功能.

3.2 接口格式

 关键字interface 接口名{}  ---- 接口的命名规则和类一样,"大驼峰命名法"

3.3 接口的特点

1)不能实例化
2)接口中成员方法:只能是抽象方法,不能有方法体;

3.4 接口如何实现

接口是比抽象类还抽象的一种概念!

接口的子类------>子实现类 (接口和实现类: 实现关系  : implements)

3.5 接口的注意事项

1)接口的子类可能是抽象类,那么肯定会存在最具体的子类,否则 没有意义!
2)具体类:就通过接口多态进行实例化!
	接口名的 对象名 = new 子实现类名() 
开发中:"接口和子实现类的定义名称的规则"
    定义接口名之后:在定义子实现类的时候:名称都会在接口名的后面+Impl

3.6 接口中的成员特点

成员变量:
	只能是常量:存在默认修饰符public static final 可以省略不写;
成员方法:
	只能是抽象方法:存在默认修饰符 public abstract 可以省略不写;
构造方法:
	接口没有构造方法,因为接口只是为了提供事物的额外功能,谁实现了接口,就具备这个功能!

3.7 面试题: 抽象类和接口的区别

1)成员区别
    接口:
    成员变量:只能是常量,存在默认修饰符 public static final  可以省略
    成员方法:只能是抽象方法,存在默认修饰符 public abstract 可以省略
                构造方法:接口没有
	抽象类:
    成员变量:即可以是常量,也可以是变量
    成员方法:既可以存在抽象方法,而且抽象方法abstract不能省略,也可以存在非抽象方法\
    构造方法:存在:无参/有参,继承关系,  先让父类初始化,然后在是子类初始化(分层初始化)

 2)关系的区别
 类与类之间关系:
	继承关系 extends  只支持单继承,不支持多继承,但可以多层继承
 类与接口之间的关系:
 	实现关系 implements一个类继承另一个类的同时,可以实现多个接口
 接口与接口之间关系:
 	继承关系 extends  不仅支持单继承,也可以多继承,也可以多层继承!

3)设计理念的区别
 抽象类:
 	存在继承关系extends, 继承体现的是"is a"的关系
 接口:
 	存在实现关系implements,仅仅是将额外功能提供相关的事物,这个事物要具备额外功能必须实现这个接口, 体现的是一种"like a"的关系

3.8 面试题: 什么时候使用继承

不能为了使用部分功能,而是使用继承,因为B类继承自A类,可以将所有方法继承过来,但是A类中有的成员方法B类可能不需要,

继承的本身弊端:
	具有局限性!

什么时候用继承的概念?

    如果B类是A类的一种,或者A类是B类一种,这个时候就可以使用继承
    继承的体系的是一种"is a"的关系!

4. 形式参数问题研究

4.1 方法的形参是基本数据类型

实际参数需要传递当前具体的基本类型的数据值即可

4.2 方法 方法的形式参数是引用数据类型:

4.2.1 具体类:
	调用该方法,实际参数需要传递的是当前具体类对象

例:

class Student{
    public void study(){
        System.out.println("学习JavaSE...");
    }
}
class StudentDemo{
    //成员方法
    public void method(Student student){ //形式参数是引用类型:Student:具体类---->实际参数需要创建Student类的具体对象
        student.study() ;
    }
}
//测试类
public class ArgsDemo1 {
    public static void main(String[] args) {
        //需要调用StudentDemo类中的method方法
        //创建StudentDemo类的对象
        StudentDemo sd = new StudentDemo() ;
        sd.method(new Student());//匿名对象
        System.out.println("---------------------------") ;
        //方式2:创建一个学生对象
        Student s = new Student() ;
        sd.method(s) ;
    }
}
4.2.2 抽象类:
抽象类: 
	调用该方法,实际参数需要传递的是当前抽象类的子类对象,抽象类多态完成!

示例:

abstract class Person{

    //定义一个非抽象方法
    /*public void work(){
        System.out.println("人都需要工作...");
    }*/
   public  abstract void work() ;
}
//定义一个类
class PersonDemo{
    //成员方法
    public void show(Person person){
                        //方法的形式参数是引用类型:抽象类--->调用该方法实际参数需要传递当前抽象类的子类对象:抽象类多态
        person.work() ;
    }
}
//抽象类不能new,需要将具体的子类定义出来
//程序员
class Programmer extends Person{
    @Override
    public void work() {
        System.out.println("程序员日日夜夜敲代码...");
    }
}
//经理
class Manager extends  Person{

    @Override
    public void work() {
        System.out.println("不断的谈需求,解决技术难点...");
    }
}
//测试类
public class ArgsDemo2 {
    public static void main(String[] args) {
        //需求:调用PersonDemo类中的show方法
        PersonDemo pd = new PersonDemo() ;
      //Person p = new Person() ; //抽象类不能实例化
       //抽象类多态
        Person p = new Programmer() ;//向上转型
        pd.show(p) ;

        Person p2 = new Manager() ;
        pd.show(p2) ;

        System.out.println("-------------------------------------") ;
        //匿名对象
        pd.show(new Manager()) ;
        pd.show(new Programmer()) ;
    }
}
4.2.3 接口
接口:
	调用该方法,实际参数需要传递的是当前接口的子实现类对象:接口多态

示例:

//定义一个接口
interface Love{
    void love() ;
}
//类
class LoveDemo{
    public void function(Love love){//方法的形式参数是引用类型:接口,
                                    //调用该方法,实际参数需要传的是当前接口的子实现类对象:接口多态
        love.love() ;
    }
}
//子实现类
class LoveImpl implements  Love{
    @Override
    public void love() {
        System.out.println("爱生活,爱Java,爱高圆圆...");
    }
}
//测试类
public class ArgsDemo3 {
    public static void main(String[] args) {
        //需求:调用LoveDemo类中的function
        LoveDemo ld = new LoveDemo() ;

        //Love lo = new Love() ;//接口不能实例化
        Love lo = new LoveImpl() ; //接口多态
        ld.function(lo) ;
        System.out.println("------------------------") ;
        //匿名对象
        new LoveDemo().function(new LoveImpl());
    }
}

5. 权限修饰符的范围

修饰符          范围 
		   在同一个包下	  在同一个包下		 在不同包下的子类中			 在不同包下的无关类中
			的当前类	   的子类中/无关类	
private 		Y	
			
默认修饰符		Y				Y

protected:	    Y				Y					Y						
受保护的 

public			Y				Y					Y							Y

四个权限修饰符的优先级: 从大到小

public > protected > 默认修饰符 >  private

6. 返回值问题的研究

6.1 方法的返回值类型: 基本数据类型:

最终通过功能的业务操作,返回的数据结果

6.2 引用数据类型(重点)

6.2.1 具体类:
如果一个方法的返回值是一个具体类,那么该方法就需要返回当前类具体对象!

示例:

class Student{
    public void study(){
        System.out.println("学习JavaEE...");
    }
}
class StudentDemo{
    //定义一个成员方法
    public Student method(){//返回值类型时一个引用类型:具体类, 调用该方法的时候,需要返回的当前具体类对象!
    
       
        //方式1:有名字对象
      Student s = new Student() ;
       return s ;

        //方式2:匿名对象
        return new Student() ;
    }
}
//测试类
public class ReturnDemo1 {
    public static void main(String[] args) {
        //需求:调用StudentDemo类的method方法
        StudentDemo sd = new StudentDemo() ;
        Student student = sd.method();//这个方法完成事情 Student student = new Student() ;
        student.study() ;
    }
}
6.2.2 抽象类:
如果一个方法的返回值是一个抽象类型,那么该方法需要返回当前抽象类的子类对象,抽象类多态!

示例:

abstract  class Person{
    //抽象方法
    public abstract void work();

}
class PersonDemo{
    public Person show(){
        //??
       // Person person = new Person() ;//抽象类不能new ,不能实例化,只能 通过抽象类多态,子类进行实例化
        //方式1:抽象类多态
        Person p = new Worker() ;
        return  p ;

        //方式2:匿名对象
        return  new Worker() ;
    }
}

//定义Person类的子类
class Worker extends  Person{

    @Override
    public void work() {
        System.out.println("爱生活,爱Java...");
    }
}
//测试类
public class ReturnDemo2 {
    public static void main(String[] args) {
        //需求:调用PersonDemo类中的show方法()
        PersonDemo pd = new PersonDemo() ;
        Person person = pd.show(); //实际业务:   Person person = new Worker() ;
        person.work() ;
    }
}
6.2.3 接口:
如果一个方法的返回值是接口类型,那么该方法需要返回的是当前接口的子实现类对象,接口多态!

示例:

interface Love{
    void love() ;
}
class LoveDemo{
    public Love function(){//方法的返回值是一个接口类型,接口不能实例化,需要返回的当前接口的子实现类对象
        //方式1:
        //接口多态
       // Love love = new LoveImpl() ;
       // return  love ;

        //匿名对象
        return  new LoveImpl() ;
    }
}

//定义子实现类
class LoveImpl implements  Love{

    @Override
    public void love() {
        System.out.println("love loveImpl...");
    }
}
//测试类
public class ReturnDemo3 {
    public static void main(String[] args) {
        //测试调用:LoveDemo中的function方法:
        LoveDemo loveDemo =new LoveDemo() ;
        Love love = loveDemo.function();
        love.love();
    }
}

7. 包在开发中的真实意义

包:package  ---目录(文件夹)的意思

开发中:都使用的多级包中间.隔开

真实开发场景中:包的命名规则
    多级包:都是公司域名反写
            istone.net.dev.xx
通过包名--------------------------->区分代码的层次结构的!
  istone.net.dev.pojo/公司域名反写.entity/公司域名.domain:
                实体类所在的包:提供这些类的属性私有化,构造方法 setXXX()/geXXX()
        User类
        Product类
        Student类

        描述现实世界的事物------"数据库中数据表"
 公司域名反写.dao:  包下存储的代码--->数据库的操作代码(JDBC:Java连接数据库)
        dao:数据访问对象data access Object

8. 内部类

8.1 什么是内部类:

	在一个类A中定义另一个类B,那么将类B就称为类A的内部类;类A是它的外部类!

8.2 内部类分类

内部类:
    成员内部类:在一个类的成员位置定义的
    局部内部类:在一个类的成员方法中定义的

8.3 成员内部类

8.3.1 特点

	成员内部类(非静态)的成员可以访问外部类的成员,包括私有!
在测试类中:
 		如何直接访问成员内部类的成员---此时该成员内部类:非静态
固定格式:
		外部类名.内部类名 对象名 = 外部类对象.内部类对象 ;

示例:

//外部类
class Outer2{
    //外部类的成员变量
    private int num = 100 ;

    //成员内部类
    class Inner2{
        //成员方法
        public void show(){
            System.out.println(num) ;
        }
    }
   //定义外部类的成员方法:访问内部类的成员
    public void method(){
        //show() ;不能这样写
        //访问Inner2成员内部类的成员:---->通过对象方法
        Inner2 inner = new Inner2() ;
        inner.show() ;
    }
}
//测试类
public class InnerClassDemo2 {
    public static void main(String[] args) {
        //创建外部类对象,访问它的method方法
      /*  Outer2 o = new Outer2() ;
        o.method() ;*/

      //直接访问
        // 外部类名.内部类名 对象名 = 外部类对象.内部类对象;
        Outer2.Inner2 oi = new Outer2().new Inner2() ;
        oi.show() ;
    }
}
8.3.2 成员内部类中的修饰符
静态的成员内部类中的成员方法(静态的还是非静态),访问外部类的成员变量,都必须是静态的
     1)静态的成员内部类随着外部类的加载而加载;
     2)如何直接访问静态的成员内部类的中成员方法
     外部类名.内部类名 对象名 = new 外部类名.内部类名() ;

示例:

//定义外部类
class Outer3{
    public int num = 100 ;
    public static int num2 = 200 ;
    //成员内部类---加入static
    static class Inner3{//类都已经是静态的了
        //里面有一个非静态方法
        public void show(){
           // System.out.println(num) ;
            System.out.println(num2) ;
        }
        //静态方法
        public static void show2(){
            //System.out.println(num) ;
            System.out.println(num2) ;
        }
    }
}
//测试类
public class InnerClassDemo3 {
    public static void main(String[] args) {

        //外部类名.内部类名 对象名  = 外部类对象.内部类对象;
       // Outer3.Inner3 oi = new Outer3().new Inner3() ; //用不了了:只能针对非静态的成员内部类

        //成员内部类是静态的------将它可以看成是"外部类的静态成员"

//        外部类名.内部类名 对象名 = new 外部类名.内部类名() ;
        Outer3.Inner3 oi =new Outer3.Inner3() ;
        oi.show() ;
        oi.show2() ;//静态方法
        System.out.println("--------------------------------------") ;
        //show2()的另一种方式
        //成员内部类是静态的------将它可以看成是"外部类的静态成员"而且静态的成员内部类中静态
        // 的成员方法
        Outer3.Inner3.show2() ; //静态的成员内部类的静态成员方法(推荐这种访问)
    }
}

8.4 匿名内部类

没有名字的类
8.4.1 格式:
  new 类名/接口名(){   一般类名--->抽象类
   重写抽象方法(){
            业务功能;
         }
       } ;
8.4.2 匿名内部类的本质:
就是继承了该抽象类或者实现了该接口子类对象;
8.4.3 应用场景:
 匿名内部类的使用在方法定义中或者是方法声明上:局部位置中使用
             public void show(抽象类名 参数名){

               }
       1)可能方法的形式参数是一个接口/抽象类
       2)可能方法返回值类型时一个接口/抽象类

示例:

//定义一个接口
interface Inter{
    //只有一个抽象方法
    void show() ;
    //多个抽象方法
    void show2() ;
}
//定义一个外部类
class Outer{
    //有一个成员方法
    public void method(){
        //局部位置
        //方法体中:需要将Inter接口中的show进行重写
             /*class  Inner implements Inter{ //局部内部类的类名Inner
            @Override
            public void show() {
            }
        }
       
/** new Inter(){
            @Override
            public void show() {
                System.out.println("show Inter...");
            }
            //重写接口中的方法
             @Override
             public void show2() {
                 System.out.println("show2 Inter...");
             }
         }.show() ;
         
 new Inter(){
            @Override
            public void show() {
                System.out.println("show Inter...");
            }
            //重写接口中的方法
            @Override
            public void show2() {
                System.out.println("show2 Inter...");
            }
        }.show2() ;  */
        //问题:当接口中的抽象方法越来越多,此时使用匿名内部类的时候,调用方法很麻烦...
        //优化:如果能够为当前匿名内部类(表示是继承了抽象类或者实现了接口的子类对象),给他起个对象名称

        Inter inter = new Inter() {//还是接口多态方式:不过子实现类没类名

            @Override
            public void show() {
                System.out.println("show Inter...");
            }

            @Override
            public void show2() {
                System.out.println("show2 Integer...");
            }
        };
        inter.show() ;
        inter.show2() ;
    }
}
//测试类
public class NoNameInnerClassDemo {
    public static void main(String[] args) {

        //创建外部类对象
        Outer outer = new Outer() ;
        outer.method() ;
    }
}

8.5 局部内部类

8.5.1 特点
局部内部类可以访问外部类的成员吗?
   可以,包括私有;
8.5.2 面试题
 面试题:
  局部内部类访问局部变量的时候,有什么要求?为什么?
      要求当前的局部变量为常量:加入final修饰 ,为什么
      jdk8 jvm已经做了内存优化:通过反编译工具查看:num2:自动带上final修饰(默认,省略了)
      jdk7以前(包含jdk7):局部内部类访问局部变量,前面必须显示的加入final修饰
 
       局部变量的生命周期随着方法的调用而存在,随着方法调用结束而消失;
	   但是局部变量还在被局部内部类的成员方法在使用,局部类的对象不会立即消失,需要等待GC回收,需要将这个变量变成常量,保证一直可以访问到!

示例:

//外部类
class Outer{
    private int num = 20 ;
  //  private int num2 = 50 ;//私有
    //成员方法
    public void method(){
        //局部变量
        final int num2 = 100 ; //jdk8 jvm已经做了内存优化:通过反编译工具查看:num2:自动带上final修饰(可以省略:优化过了)
        //定义局部内部类
        class Inner{
            //成员方法
            public void show(){
                //访问局部变量num3
                System.out.println(num) ;
                System.out.println(num2) ; //还在使用变量num2
               // System.out.println(num2) ;
            }
        }

        //外部类的当前这个成员方法中:创建局部内部类对象,调用show
        Inner inner = new Inner() ;
        inner.show();
    }
}

//测试类
public class InnerClassDemo1 {
    public static void main(String[] args) {

        //创建外部类对象
        Outer outer = new Outer() ;
        outer.method() ;
    }
}

9. Object 类

	Object是类Object结构的根。 每个类都有Object作为超类(父类)

9.1 常用功能

大部分常用类已经将这些功能重写了
   public final Class getClass():表示正在运行的类的实例!   (当前类的字节码文件对象)(重点)
   public int hashCode():哈希码值,把它可以看成是一个"地址值",不是真实意义的地址值,和哈希表有关!(了解)
              不同的对象,哈希码值不同
        Class---->后期反射中讲
成员方法:
   public String getName():获取当前正在运行的的类名,表现字符串形式
9.2 常用类
JavaSE---->JavaEE:做项目中会使用大量的写Java中常使用的接口或者类
举例: 
	集合   String    Date日期  StringBuffer 线程Thread    IO流程:InputStram/OutputStream:数据传输      网络编程     反射

10. 面试题:获取一个类的字节码文件对象的方式有几种?

	1)Object的方法 public final Class getClass()
	2)任意Java类型的class属性
	3)

11. 带包的编译额运行

11.1 在同一包下:

首先:创建package包名(推荐多级包:中间点隔开,分包)
		两种情况:
			1)手动方式:
				a)将你当前的多级包名创建出来
				b)先将当前的Java文件进行编译
					在当前目录中:使用javac java源文件 ---->.class文件
				c)将当前字节码文件存储在刚才1)包下
				d)带包进行运行
					java 包名.类名 
					
			D:\EE_2110\day15\code\01_同一个包下的编译和运行>javac Demo.java
			D:\EE_2110\day15\code\01_同一个包下的编译和运行>java com.qf.Demo
			demo...
			D:\EE_2110\day15\code\01_同一个包下的编译和运行>	

			2)自动方式:
				a)对Java文件进行编译
				javac -d . 某个Java文件 ---->自动的产生包名和字节码文件
				b)带包进行运行
					java 包名.类名
					
			D:\EE_2110\day15\code\01_同一个包下的编译和运行>javac -d . Demo.java
			D:\EE_2110\day15\code\01_同一个包下的编译和运行>java com.qf.Demo
			demo...
			D:\EE_2110\day15\code\01_同一个包下的编译和运行>	

11.2 在不同包下的编译和运行

直接使用自动方式
			1)将当前Demo类先进行编译
				javac -d . Demo.java
			2)将Test类进行编译
				pakcage和class中间:import 包名.类名;
				javac -d . Test.java---
				它里面用到Demo类,需要导包,而且必须保证当前类的访问权限足够大
			3)运行 com.qf.Test类
				java com.qf.Test

12. Object类中的方法

12.1 public String toString()

	返回对象的字符串表示形式
如果方法没有被重写:
	New对象,输出对象名打印的会是地址值,没有实际意义.
所以建议所有子类覆盖此方法:
	输出对象名称,看到的是当前这个对象的成员信息表达式!

12.2 public boolean equals(Object obj):

	指示其他对象与此对象是否"相等"
==和equals的区别:
    ==:连接的是基本数据类型:比较的基本数据类型数据值是否相等
            int a= 10 ;
             int b = 20 ;
             a==b ;

    ==:连接的是引用数据类型,比较的是引用数据类型的地址值是否相同

   equals:默认比较的是地址值是否相同,建议子类重写equals方法,比较他们内容是否相同(成员信息是否相同)
   在重写equals方法的同时,还需要重写hashCode()方法,保证哈希码值必须一样,才能比较equals
   
    alt+ins--->equals and hashCode
    如果重写Object类的equals方法之后,都是比较的内容是否相同(成员信息是否相同)

   大部分的常用类都会重写Object类的equals方法

12.3 protected Object clone(): 浅克隆

 throws CloneNotSupportedException:调用过程中可能存在克隆不支持的异常
  对于jdk提供的类的方法本身存在异常.谁调用这个方法,必须做出处理,否则报错,最简单的方式继续往上抛 throws
  	创建并返回此对象的副本(浅克隆) :了解
   	简单理解:复制对象,获取对象的成员...

13. Scanner类

java.util的类:文本扫描器,不属于lang包下,使用必须导包
构造方法
  public Scanner(InputStream source)

成员方法:
     判断功能 haxNextXXX():判断下一个录入都是是否是XXX类型
     public boolean hasNextInt():
     public boolean hasNextLine().

获取功能    nextXXX()
     public int nextInt()
     public String nextLine()
     public String next()
        ...

13.1 键盘录入的细节:

录入的字符串和,int类型
       先录入int,在录入字符串:字符串数据被漏掉
原因:
		"回车符号"的问题,如何解决:
        1)可以使用next()---->录入的也是字符串
        2)在录入String之前,在创建一个新键盘录入对象:比较麻烦:比较耗内存

14. String类(重点)

14.1 String的描述

	String类代表字符串。
	'Java程序中的所有字符串文字(例如"abc" )都被实现为此类的实例。 "字符串本身就是常量"

14.2 String的特点:

	字符串不变的; 它们的值在创建后不能被更改
推荐方式:
    String 变量名   =  "字符串常量" ;

14.3 String类的构造方法:

    public String():无参构造
    String(byte[] bytes):将字节数组可以构造字符串对象
    public String(byte[] bytes,int offset,int length)一部分字节数组构造成字符串对象
    public String(char[] value):将字符数组构造成字符串对象
    public String(char[] value, int offset,int count):将一部分字符数组构造成字符串对象
    public String(String original):创建一个字符串对象,里面存储字符串常量

14.4 String的判断功能

    public boolean contains(String s):判断是否包含子字符串
    public boolean startsWith(String prefix):判断是以指定的字符串开头
    public boolean endsWith(String suffix):判断是是以指定的字符串结尾
    boolean equals(Object anObject)  :判断字符串内容是相等:区分大小写 
    boolean equalsIgnoreCase(String anotherString)  :判断字符串内容是否相等,忽略大小写
    public boolean isEmpty():判断字符串是否为空

14.5 String类的转换功能:

    public char[] toCharArray():将字符串转换字符数组
    byte[] getBytes()  :使用平台的默认字符集进行编码过程:将字符串--->字节数组
    byte[] getBytes(String charset):使用指定的字符集进行编码  "GBK/UTF-8"
                编码和解码
                            编码:将能看懂的字符串---->看不懂的字节
                         解码:将看不懂的字节----->能看懂的字符串
    public String toLowerCase():将字符串中的每一个字符转换成小写
    public String toUpperCase():将字符串中的每一个字符转换成大写
    static String valueOf(boolean b/float/long/double/int/char /....Object)
    万能方法:
    将任意的数据类型转换成String :静态的功能

14.5 String类的获取功能:

    char charAt(int index)  :获取指定索引出的字符值
    public String concat(String str):拼接功能:拼接新的字符串
    public int indexOf(int ch):返回指定字符第一次出现的字符串内的索引
    int lastIndexOf(int ch)  :查询指定字符最后一次出现的索引值
    int length()  :获取字符串长度
    public String[] split(String regex):字符串的拆分方法:返回的字符串数组 (重要)
    String substring(int beginIndex) :字符串截取功能   (重要)默认从beginIndex起始索引截取到末尾
    public String substring(int beginIndex,int endIndex)    :从指定位置开始截取到指定位置结束(包前不包后)
    包含beginIndex位置,不包含endIndex位置,包含到endIndex-1

14.6 String类的其他功能:

    public String replace(char oldChar,char newChar):将新的字符值把旧的字符替换掉
    public String replace(String oldChar,String newChar):将新的字符串值把旧的字符串替换掉
    public String replaceAll(String regex,String replacement):使用指定的replacement替换的字符串内容
     将符号正则表达式的匹配的字符串替换掉 (用到正则表达式使用)
    参数1:正则表达式   举例: [0-9]

      public String trim():去除字符串前后两端空格
                 一般用在:IO中传输文件(读写文件)

14.7 字符串的特点:

字符串不变的; 
 	它们的值在创建后不能被更改
      值:常量地址值...
字符串是常量:
	在内存中:方法区中的常量池中存储(池化技术...)

14.8 面试题

String s = "hello" ;
 和
String s2 = new String("hello") ;两个有什么区别,分别创建了几个对象!

   共同点:
   	都是在创建一个字符串对象"hello"
   但是内存执行不一样
         前者:只是在常量池中开辟空间,创建一个对象  :推荐这种方式,节省内存空间!
          后者:在堆中开辟空间,而且里面存在常量----常量池中标记 ,创建两个对象

14.9 面试题: 数组中有没有length(),字符串String类中有没有length(),集合中有没有length()?

数组:
	没有length(),只有length属性
String:
	有长度方法.  str.length()
集合:
	没有----获取长度:size()
    public int length():获取字符串长度
    
 null  :空值 :没有对象 引用数据类型的默认值
        String s = null ;
        String s  = "" ; 空字符序列,有,是空的,存在对象!// String s = new String("") ;

14.10 面试题: 考源码

    ublic int compareTo(String anotherString)    :如何进行字典比较
     String s1 = "hel" ;
     String s2 = "hello" ;
    结果是多少,为什么这个值?
public class StringDemo2 {
    public static void main(String[] args) {
        String s1 = "hel" ;
        String s2 = "abc" ;
        String s3 = "hello" ;

        //public int compareTo(String anotherString)    :如何进行字典比较
        //英文字符:字典顺序比较:abcdefgh....
        System.out.println(s1.compareTo(s2)) ;
        System.out.println(s1.compareTo(s3)) ;
    }
}
/**
字典顺序比较: 
	1)如果从第一个字符开始,就不同,结果就是.前的对象第一个字符对应的ASCII码表得值减去后一个字符的值.
	2)第一个相同: 开始比较往后比较,如果有不同的,再用ASCII码表值相减.
	3)短的字符串属于长的字符串子串,则值是.前的对象长度减去点后的对象长度.
*/

14.11 String,作为形式参数传递,有什么特点?

    String类型作为形式参数和基本类型作为形式的效果一样,
    形式参数的改变不会直接影响实际参数,String类型特殊的引用类型!

	其他引用数据类型,形式参数的改变会直接影响实际参数!

15. Integer类

15.1 拆装箱

jdk7以后:自动拆装箱特性
    基本数据类型---->默认提示为   引用数据类型  "装箱"
    引用数据类型------>基本数据类型            "拆箱"

15.2 类型转换

    byte           Byte
    short          Short
    int            Integer
    long           Long
    float          Float
    double         Double
    char            Character
    boolean         Boolean
Integer:Integer类包装一个对象中的原始类型int的值
         //public static String toBinaryString(int i):将整数转换字符串形式的二进制
          public  static String toOctalString(int i)  :将整数转换字符串形式的八进制
         public static String toHexString(int i):将整数转换成字符串形式的十六进制

示例:

public class IntegerDemo {
    public static void main(String[] args) {

        //求出一个数据的十进制---->二进制  八进制 十六进制
        System.out.println(Integer.toBinaryString(100)) ;
        System.out.println(Integer.toOctalString(100)) ;
        System.out.println(Integer.toHexString(100)) ;

        //求出int类型的取值范围
        //静态的常量值
        //public static final int MAX_VALUE
        //public static final int MIN_VALUE
        System.out.println(Integer.MIN_VALUE) ;
        System.out.println(Integer.MAX_VALUE) ;
    }
}

15.3 Integer的构造方法

Integer(int value):将int类型构造成Integer对象
Integer(String s) throws NumberFormatException :将String类型构造成Integer对象
          前提条件:要使用第二个构造方法,前提是必须是数字字符串

示例:

public class IntegerDemo2 {
    public static void main(String[] args) {

        //有一个int类型
        int i = 100 ;
        // Integer(int value):将int类型构造成Integer对象
        Integer ii = new Integer(i) ;
        System.out.println(ii); //100

        System.out.println("-------------------------") ;

        //String s = "hello100" ;
        String s = "200" ;

        //Integer(String s) throws NumberFormatException
        Integer i2 = new Integer(s) ;
        System.out.println("i2:"+i2) ;//200
    }
}

15.4 看程序,写结果

Integer 变量名 = 整数;
执行底层:Integer的静态功能valueOf(int i)
      public static Integer valueOf(int i) {
         //静态的成员内部类:内部缓存区:IntegerCache
         if (i >= IntegerCache.low && i <= IntegerCache.high){
                  //看当前传进来的整数值是否在-128-127之间
          return IntegerCache.cache[i + (-IntegerCache.low)];  //从内部缓存区中取出数据
            }
         return new Integer(i); //如果没有在范围内:就会创建新的Integer对象
     }

示例:

	  Integer i9 = 128 ;    // 记住取值范围:  -128-127
	  Integer i10 = 128 ;
      System.out.println(i9==i10) ; //false
      System.out.println(i9.equals(i10));//true

16. StringBuffer类

	简称"字符串缓冲",线程安全的,而且可变的字符序列!

16.1 线程(Thread)

    单线程 :程序的执行路径只有一条 ,不考虑安全性,只考虑效率!
    多线程 :程序的执行路径有多条,考虑安全性,效率问题不是重点!

16.2 面试题

StringBuffer和StringBuilder有什么区别?
共同点:
	两者都是字符串区,支持可变的字符序列,而且都有互相兼容的API(功能相同的)
不同点:
	前者:线程安全的类,多线程环境下使用居多-----同步(安全)----->执行效率低
		行的网站/医疗网站(不是谁都能随便搞事)
	后者:线程不安全的类,单线程程序中使用居多---->不同步(不安全)----->执行效率高\
		论坛的网站...(有水军能匿名搞事)

16.3 StringBuffer的构造方法

    StringBuffer();无参构造方法  :使用居多
    StringBuffer(int capacity):指定容量大小的字符串缓冲区
    tringBuffer(String str) :指定缓冲区的具体内容str,容量大小=16个默认容量+当前字符串长度
    public int length()获取字符缓冲区中的长度
    public int capacity():获取字符串缓冲区中的容量大小

示例:

public class StringBufferDemo{
    public static void main(String[] args) {
        // StringBuffer();无参构造方法
        //创建一个字符串缓冲区对象
        StringBuffer sb = new StringBuffer() ; //默认的初始化容量16个(足够用了)
        System.out.println("sb:"+sb) ;
        System.out.println(sb.length()) ;
        System.out.println(sb.capacity()) ;
        System.out.println("-------------------------") ;

        //  StringBuffer(int capacity):指定容量大小的字符串缓冲区
        StringBuffer sb2 = new StringBuffer(50) ;
        System.out.println("sb2:"+sb2);
        System.out.println(sb2.length());
        System.out.println(sb2.capacity());

        System.out.println("-------------------------") ;

       // StringBuffer(String str) :
        String s = "helloworld" ;
        StringBuffer sb3 = new StringBuffer(s) ;
        System.out.println("sb3:"+sb3);
        System.out.println(sb3.length() );
        System.out.println(sb3.capacity() );

        //StringBuffer sb4 = "hello" ; //不能这样写
       /* String str = "hello" ;
        StringBuffer sb4 = str ;*/
    }
}

16.4 添加/删除

添加字符序列:
      StringBuffer append(任何数据类型):将任何数据类型的数据追加字符序列中(字符串缓冲区)
      StringBuffer insert(int offset, String str)  :插入元素:在指定位置插入指定的元素
删除字符序列:
      public StringBuffer deleteCharAt(int index):在指定的位置处删除的指定的字符,返回字符串缓冲区本身
      public StringBuffer delete(int start,int end):删除指定的字符从指定位置开始,到end-1处结束

16.5 反转功能

	public StringBuffer reverse():反转功能

示例:

public class StringBufferDemo3 {
    public static void main(String[] args) {
        //已知一个字符串:
     /*   String s = "helloworld" ;
        //s---->StringBuffer类型
        StringBuffer sb = new StringBuffer(s) ;

        //利用功能
        StringBuffer sb2 = sb.reverse();
        String result = sb2.toString();
        System.out.println(result);*/

     //键盘录入一个字符串:将字符串反转
        Scanner sc = new Scanner(System.in) ;

        //提示并录入数据
        System.out.println("请您输入一个字符串:") ;
        String line = sc.nextLine() ;

        //调用功能改进---->String
        String result = reverse(line);
        System.out.println(result);
    }
    public static String reverse(String s){
        //s---->StringBuffer
        //分步实现
//        StringBuffer sb = new StringBuffer(s) ;
//        //反转---并且转换String
//        String result = sb.reverse().toString();
//        return  result ;
        //一步走
        return  new StringBuffer(s).reverse().toString() ;
    }
}

16.5 开发中利用类型转换

开发中:引用类型
	有可能将A类型转换成B类型,结果最终需要的是B类型
    有的时候,A类型---->B类型----->A类型
	可能需要用B类型的功能,但是结果需要的是A类型,又需要转回去
	 StringBuffer <-----> String

示例:

public class StringBufferTest {
    public static void main(String[] args) {

        //String------->StringBuffer
        //方式1:使用StringBuffer的有参构造方法
        //StringBuffer(String s)
        String s = "helloJavaEE" ;
        StringBuffer sb = new StringBuffer(s) ;
        System.out.println("sb:"+sb) ;//内容一样,但是数据类型不同
        System.out.println("------------------------------") ;

        //方式2:使用StringBuffer无参构造方法+append(String s)
        StringBuffer sb2 = new StringBuffer() ;
        sb2.append(s) ;
        System.out.println("sb2:"+sb2) ;


        System.out.println("------------------------------------------") ;
        //StringBuffer-------->String
        //有一个StringBuffer的数据
        StringBuffer buffer = new StringBuffer("android") ;
        //String类型构造方法:public String(StringBuffer buffer)
        String str = new String(buffer) ;
        System.out.println("str:"+str) ;

        System.out.println("------------------------------------------") ;
        //public String toString()
        String str2 = buffer.toString();
        System.out.println("str2:"+str2);
    }
}

16.6 String的截取类型

    String substring(int start):从指定位置截取到默认结束,返回的新的字符串
    String substring(int start, int end) :从指定位置开始截取,到指定位置结束(包前不包后)

示例:

public class StringDemo4 {
    public static void main(String[] args) {

        StringBuffer sb = new StringBuffer() ;
        sb.append("helllo") ;
        sb.append("world") ;
        System.out.println(sb) ;

        //截取
        String resultStr = sb.substring(5);
        System.out.println(resultStr) ; //返回的被截取的字符串内容

        System.out.println("-------------------------------------") ;
        String resultStr2 = sb.substring(5, 9);
        System.out.println(resultStr2);
    }
}

17. 面试题: String和StringBuffer有什么区别?

前者:  
	String是常量,一旦被赋值,其值不能被更改;它的不可变的字符序列
      开发中:前端提交后台的数据--------> String (它的功能远远大于StringBuffer)
      作为形式参数,形式参数的改变不会影响实际参数,特殊的引用类型,和基本数据类型作为形式参数的效果一样

后者: 
	StringBuffer是可变的字符序列,线程安全的类,同步,执行效率低,单线程程序中的使用StringBuilder替代		StringBuffer
     字符串缓冲区 里面存储的字符序列-------> 还需要转换成String类型
    作为形式参数,形式参数的改变会直接影响实际参数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值