java对象篇
一、面向对象编程(OOP)
- 面向对象和面向过程
- 
面向过程思想:线性思维 - 
步骤清晰简单,顺序执行 
- 
适合处理一些较为简单的问题 
 
- 
- 
面向对象思想 - 
物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独的思考。最后才对某个分类下的细节进行面向过程的思索。 
- 
合适处理复杂的问题,适合处理需要多人协作的问题 
 
- 
- 
对于描述复杂的事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。 
- 面向对象:
- 本质:以类的方式组织代码,以对象形式的组织(封装)数据
- 抽象:将一个对象的共同特性抽取出来
- 三大特性:
- 封装
- 继承
- 多态
 
- 从认识的角度来考虑是先有对象后有类。对象是具体的事物。类是抽象的,是对对象的抽象。
- 从代码运行的角度考虑是先有类后有对象。类是对象的模板。
二、回顾方法的定义和调用
1.方法的定义
- 
修饰符 
- 
返回类型 
- 
break return的区别:  break语句的使用场合主要是switch语句和循环结构。在循环结构中使用break语句,如果执行了break语句,那么就退出循环,接着执行循环结构下面的第一条语句。如果在多重嵌套循环中使用break语句,当执行break语句的时候,退出的是它所在的循环结构,对外层循环没有任何影响。如果循环结构里有switch语句,并且在switch语句中使用了break语句,当执行switch语句中的break语句时,仅退出switch语句,不会退出外面的循环结构。  continue语句是这5种结束循环的方式中最特殊的,因为它并没有真的退出循环,而是只结束本次循环体的执行,所以在使用continue的时候要注意这一点。  如果在程序中遇到return语句,那么代码就退出该函数的执行,返回到函数的调用处,如果是main()函数,那么结束整个程序的运行。 
- 
方法名 
- 
参数列表 
- 
异常抛出 
2.方法的调用
- 静态方法:static,通过类名可直接调用
- 非静态方法:需要实例化后调用
非静态方法可以调用静态方法和非静态方法
public void Method1(){
    Method2();
    Method3();
}
public static void Method2(){}
public void Method3(){}
静态方法只能调用静态方法
public static void Method1(){
    Method2();
    //只有实例化后才可以调用非静态方法
    //Method3();报错
}
public static void Method2(){}
public void Method3(){}
- 形参和实参
- 值传递和引用传递
//值传递,不会改变原有的数据
public static void main(String[] args) {
    int a=1;
    System.out.println(a);
    Change(a);
    System.out.println(a);
}
public static void Change(int a){
    a=100;
}
//两次输出都是1
//引用传递
public class MethodDemo02 {
    public static void main(String[] args) {
        Person person =new Person();
        System.out.println(person.name);//默认为空,输出null
        person.name="韩小小";
        System.out.println(person.name);//输出韩小小
    }
}
//一个类中只能有一个public
 class Person{
    String name;
}
- this关键字
- 递归
三、对象的创建
- 
类和对象的关系 - 类是一种抽象的数据类型,它是对某一类事物整体的描述或定义,但是并不代表一个具体的事物
- 对象是抽象概念的具体实例
 
- 
创建与初使化对象 - 
使用new关键字 
- 
使用new关键字的时候,除了分配内存空间外,还会给创建好的对象进行默认初使化以及对类中的构造器的调用 
- 
类中的构造器也称为构造方法,是在进行创建对象的时候必须调用的,并且构造器有以下两个特点 - 必须和类的名字相同
- 必须没有返回值,也不能写void
 alt+ins快捷插入构造方法 构造方法的作用是 1.当用new初使化对象时会调用 2.可以用来初使化类中的字段 构造方法如果显式的定义了,则默认就不生成不带参数的构造方法
 
- 
四、创建对象内存分析

当程序运行时,会首先在堆中的方法区内加载类的信息,如方法、常量(放在常量池中),同时将在静态方法区中加载静态方法和静态变量;然后会将main方法的引用压入到栈的最底层,当对象创建时,将对象的引用依次压入栈中,栈中的引用指向椎中的内存,对象成员赋值时,读取方法区的信息进行赋值;可直接调用静态方法区的方法
五、封装
- 该露的露,该藏的藏
- 程序设计追求“高内聚,低耦合”。
- 高内聚:类的内部数据操作细节自己完成,不允许外部干涉
- 低耦合:仅暴露少量的方法给外部使用,就是说两个相关的模块尽可以能把依赖的部分降低到最小,不要让两个系统产生强依赖
 
 
- 程序设计追求“高内聚,低耦合”。
- 封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中数据的实际表示,而应该操作接口来访问,这称为信息隐藏
 
- 记住:属性私有,get/set
- 封装的好处
- 提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 系统可维护性增强
 
六、继承
- 继承的本质是对某一批类的抽象,从而现实对现实世界更好的建模
- 用extends关键字,意思是“扩展”,子类是父类的扩展
- java只有单继承
- 继承是类和类之间的一种关系,除此之外,类与类之间还有依赖、组合、聚合等关系
- 继承是一种is a的关系
七、super和this
super:
- 代指父类对象,可通过super.来调用父类中的成员
- 当new一个子类对象时,默认会去调用父类的构造方法,其写法上省略了一个super();
- super()在构造函数中是调用父类的构造器,必须要匹配起来,若重写了带参数的构造器,则默认的不带参数的构造器会被删除
- super或this调用构造方法必须放在构造方法的第一行
this:
- 代指当前类的对象,可通过this.来调用当前对象的成员
//父类
public class Person {
    public Person(int age) {
        this.age = age;
    }
     int age=50;//修饰符为默认的,不用写
     public void Test1(){
         System.out.println("this is father calss");
     }
}
public class Teacher extends Person{
    public Teacher() {
        super(5);//调用父类的构造器,并传给父类参数
        this.age=10;
    }
    public int age=10;
    public void Test(int age){
     	System.out.println(this.age);//输出10,当前对象的age
        System.out.println(age);//输出5,传递过来的参数,若没有传参,则为当前对象
        System.out.println(super.age);//输出0,父类的age,但如果父类成员的修饰符为private,则无法调用
        Test1();//输出子类的Test1方法
        this.Test1();//输出子类的Test1方法
        super.Test1();//输出父类的Test1方法
    }
}
public class Application
{
    public static void main(String[] args) {
        Teacher teacher=new Teacher();
        teacher.Test(5);
    }
}
八、方法重写
- 重写是针对类的方法的,若父类方法和子类方法全是static修饰,则对象调用的方法和声明的对象类型有关,static方法和重写没什么关系,因为在类加载时static方法就已经被加载到静态方法区了
public class A {
    public static void Test(){
        System.out.println("A-->Test");
    }
}
public class B extends A{
    public static void Test(){
        System.out.println("B-->Test");
    }
}
public static void main(String[] args) {
      A b = new B();
      b.Test();//调用A类的方法
      B b1 = new B();
      b1.Test();//调用B类的方法
}
- 若存在继承关系,子类会重写父类的方法,如下,在new对象时,将父类的引用指向了子类,可以用上面的原理图来理解,子类重写了父类的方法,因此调用父类的方法,就是调用子类重写后的方法

- 修饰符的范围:子类的范围可以扩大,但不可以缩小,就是说不能比父类的访问级别低 ,默认的修饰符是空,含义是指在同一个包下的
- 异常的抛出可以被缩小,不能被放大
- 当父类的功能子类不需要或不能满足子类时,可进行方法的重写
九、多态(父类引用指向子类对象)
- 
动态编译:类型:可扩展性 ,只有在程序运行的后才能确定对象的类型 
- 
即同一方法可以根据发送对象的不同而采用多种不同的行为方式 
- 
一个对象的实际类型是确定的,但可以指向对象的引用类型有很多 
- 
多态存在的条件 - 有继承关系
- 子类重写父类的方法
- 父类引用指向子类对象Father f1=new Son();
 
- 
有三种方法不能重写 - static静态方法,属于类,不属于实例
- final:常量,存在于常量池中
- private方法
 
- 
注意:多态是方法的多态,属性是没有多态性的 

public class Person {
    public  void Run(){
        System.out.println("Person run");
    }
}
public class Student extends Person{
    @Override
    public void Run() {
        System.out.println("Student run");
    }
    public void Eat(){
        System.out.println("Student eat");
    }
}
public static void main(String[] args) {
    //一个对象的实际类型是确定的
    // new Student()
    // new Person()
    //可以指向的引用是不确定的,父类可以指向子类的引用
    Student s1 = new Student();//Student能调用的对象都是自己的或继承父类的
    Person s2 = new Student();//Person类指向子类,但不能调用子类独有的方法
    Object s3=new Student();
    //如果不重写子类的方法,则调用Run全都会调用父类的方法,因为子类继承了父类的方法
    //如果子类重写了父类的方法,则调用Run都会输出子类重写后的方法,子类已经重写了父类的方法
    s1.Run();
    s2.Run();
    //对于子类中父类没有方法,父类对象无权调用,除非使用强制类型转换
    s1.Eat();
    ((Student)s2).Eat();
}
- 总结:
- 所谓多态就是子类重写了父类的方法,当把父类对象指向子类时,父类对象会表现出子类对象的特征,也就是调用子类重写后的方法,从而实现一个同一方法表现出不同的行为(父类对象直接调用父类本身的方法,以及父类对象指向子类对象调用子类重写后的方法)。
- 父类对象不能调用子类独有的方法
- 要实现多态必须要有继承关系
 
十、instanceof和类型转换
instanceof:
- 
instanceof的作用是判断一个对象是什么类型,以及子类和其他类是否存在父子关系,存在返回true,否则为false 
- 
System.out.println(X instanceof Y);能否通过编译,取决于X和Y类型有没有父子关系 
- 
System.out.println(X instanceof Y);是否为true,则取决于X所指向的实际类型是不是Y类型或者其子类型 
- 
简单来说intanceof是用来判断一个对象是不是一种类型或者其子类型,是返回true,否则为false 
- 
instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例,用法为: boolean result = obj instanceof Class其中 obj 为一个对象,Class 表示一个类或者一个接口,当 obj 为 Class 的对象,或者是其直接或间接子类,或者是其接口的实现类,结果result 都返回 true,否则返回false。 注意:编译器会检查 obj 是否能转换成右边的class类型,如果不能转换则直接报错,如果不能确定类型,则通过编译,具体看运行时定。 Object obj=new Student(); System.out.println(obj instanceof Student); System.out.println(obj instanceof Person); System.out.println(obj instanceof Object);//子类的实例化需要先调用父类的构造方法,父类是包含于子类的,因此在判断时,返回true System.out.println(obj instanceof Teacher); System.out.println(obj instanceof String); System.out.println("++++++++++++++++++++++++++"); Person Per=new Student(); System.out.println(Per instanceof Student); System.out.println(Per instanceof Person); System.out.println(Per instanceof Object);//子类的实例化需要先调用父类的构造方法,父类是包含于子类的 System.out.println(Per instanceof Teacher); //System.out.println(Per instanceof String);//编译不通过 System.out.println("++++++++++++++++++++++++++"); Student stu=new Student(); System.out.println(stu instanceof Student); System.out.println(stu instanceof Person); System.out.println(stu instanceof Object);//子类的实例化需要先调用父类的构造方法,父类是包含于子类的 //system.out.println(stu instanceof Teacher);//编译不通过 //System.out.println(Per instanceof String);//编译不通过 //student\person\object类均输出true,其他为false
引用类型类型转换:
- 子类转父类可以直接进行转换,可能丢失方法,子类的独有方法不能被父类调用
- 父类转子类需要进行强制转换
- 优点:方便方法的调用,减少代码重复,使代码更简洁
            //Student类是Person类的子类,Eat方法为Student类独有
			//父类引用指向子类对象
            //子类转父类可以直接转,但会损耗一些方法(子类的方法父类无法调用)
            //父类转子类,需要强制类型转换
            Student stu=new Student();
            stu.Eat();
            Person stu1 = stu;
            //stu1.Eat();无法调用
            ((Student)stu1).Eat();
十一、静态static
static
对象可以调用静态属性,也可以通过类名调用,推荐使用类名调用,静态属性被类中的实例所共享。
静态方法不能调用动态方法,因为静态方法在类加载的时候加载的,而动态方法是在创建对象的时候加载的。
public class Student {
    private static int age;//静态属性
    private int score;//非静态属性
    public void run(){
        Student.go();
        go();
    }
    public static void go(){
        //run(),静态方法不能调用动态方法,因为动态方法是属于对象的,只有在对象创建后并通过对象来调用
    }
    public static void main(String[] args) {
        Student st1=new Student();
        System.out.println(st1.age);
        System.out.println(st1.score);
        System.out.println(Student.age);//推荐,静态成员能被类中的实例所共享
        go();
        Student.go();
        new Student().run();
    }
}
代码块和静态代码块
- 
在创建对象时,执行构造方法之前还会执行匿名代码块以及静态代码块,静态代码块在程序中只能执行一次 
- 
执行顺序 :静态代码块->匿名代码块->构造方法 
public class Person {
    static {
        //代码块
        System.out.println("静态代码块");//Java静态代码块中的代码会在类加载JVM时运行,且只被执行一次
    }
    {
        //代码块
        System.out.println("匿名代码块");
    }
    public Person() {
        System.out.println("构造方法");
    }
    public static void main(String[] args) {
        new Person();//静态代码块先执行,然后是匿名代码块,最后是构造方法
        System.out.println("=========================");
        new Person();//静态代码块只执行一次,这里只输出匿名代码块和构造方法
    }
}
静态导入包
静态导入包,可直接调用包中的静态方法
//静态导入包,可直接调用包中的静态方法
import static java.lang.Math.random;
import java.lang.Math;
public class Test {
    public static void main(String[] args) {
        System.out.println(Math.random());
        System.out.println(random());
    }
}
十二、抽象类
- 抽象类要用abstract来实现
- 抽象类中的抽象方法要加abstract
- 不能创建抽象类的对象,只能用子类来实现
- 单继承
- 抽象类就是一种约束
- 抽象类中也有构造方法
十三、接口
- 对比:
- 普通类:只有具体实现
- 抽象类:具体实现和规范(抽象方法)都有
- 接口:只有规范
 
- 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是...则必须能...”的思想。
- 接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。
- OO的精髓,是对对象的抽象,接口最能体现这一点。
- 我们讨论设计模式都只针对具备了抽象能力的语言,就是因为设计模式所研究的,实际上就是如何合理的去抽象。
- 声明接口的关键字是interface
- 接口没有构造方法
- 接口中可以有属性,为常量,默认属性省略public static final
- 接口中方法默认为public abstract修饰,一般省略
public interface InterTest {
    void test();
    int test2();
}
public interface UserService {
    int AGE=99;// 默认属性省略public static final,常量
    public static final int AGE2=98;
    void add();
    public abstract void del();
    void up();
    void query();
}
public class UserDemoImpl implements InterTest, UserService {
    @Override
    public void test() {
    }
    @Override
    public int test2() {
        return 0;
    }
    @Override
    public void add() {
    }
    @Override
    public void del() {
    }
    @Override
    public void up() {
    }
    @Override
    public void query() {
    }
}
十四、内部类
- 成员内部类
public class NumInnerClass {
    private int ID=66;
    public void Test(){
        System.out.println("this is outter class method");
    }
    //注意public关键字
    public class InnerClass{
        public void Test(){
            System.out.println("this is inner class Test");
        }
        public void Test1(){
            System.out.println("this is inner class Test1");
        }
        public void Test3(){
            System.out.println(ID);//可调用外部类的private成员
        }
    }
}
public class Application {
    public static void main(String[] args) {
        NumInnerClass numInnerClass=new NumInnerClass();
        numInnerClass.Test();
        NumInnerClass.InnerClass ic = numInnerClass.new InnerClass();//要通过对象.来进行实例化
        ic.Test();
        ic.Test1();
        ic.Test3();
    }
}
- 静态内部类(static)
public class NumInnerClass {
    private static int ID=66;
    public void Test(){
        System.out.println("this is outter class method");
    }
    public static class InnerClass{
        public static void Test1(){
            System.out.println("this is inner class Test1");
        }
        public static void Test3(){
            System.out.println(NumInnerClass.ID);//不能调用非静态成员
        }
    }
}
public class Application {
    public static void main(String[] args) {
        NumInnerClass numInnerClass=new NumInnerClass();
        numInnerClass.Test();
        NumInnerClass.InnerClass.Test3();
        NumInnerClass.InnerClass.Test1();
    }
}
- 局部内部类
public class Test {
    public void method01(){
        //局部内部类
        class A {
            int age=1;
        }
        A a = new A();
        System.out.println(a.age);
    }
}
public class Application {
    public static void main(String[] args) {
        Test test = new Test();
        test.method01();
    }
}
- 匿名内部类
public class Test02 {
    public static void main(String[] args) {
        new Apple().eat();
       	Luzhenguo luzhenguo = new Luzhenguo() {
            @Override
            public void test05() {
            }
        };
    }
}
class Apple{
    public void eat(){}
}
interface  Luzhenguo{
   void test05();
}
十五、异常机制Exception
- 异常指程序中出现的不期而至的各种状况,如文件找不到、网络连接失败
- 异常发生在程序运动期间,它影响了正常的程序执行
异常的简单分类:
 1.检查性异常: 不处理编译不能通过,如打开一个文件不存在
 2.非检查性异常:不处理编译可以通过,如果有抛出直接抛到控制台,如空指针
public static void main(String[] args) {
    System.out.println(11/0);//ArithmeticException
}
 3.运行时异常: 就是非检查性异常
 4.非运行时异常: 就是检查性异常
 5.错误:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略,如栈溢出
public class ExceptionDemo {
    public static void main(String[] args) {
        new ExceptionDemo().a();//Exception in thread "main" java.lang.StackOverflowError
    }
    public void a(){
        b();
    }
    private void b() {
        a();
    }
}
java的异常体系结构

Error
- Error类对象由java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。
- java虚拟机运行错误(Virtual MachineError),当JVM不再有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发生时,java虚拟机(JVM)一般会选择线程终止。
- 还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError)、链接错误(LinkageError)。这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。
Exception

十六、异常处理机制
throw
package Demo06;
public class Test {
    public static void main(String[] args) {
        //ctrl+alt+T
        try {//需要捕获的内容
            int a=11,b=0;
            if (b==0){
                throw new ArithmeticException();//throw关键字可直接抛出异常
            }
            System.out.println(a/b);//此处程序不会走
        } catch (Exception e) {
            //对抛出异常的处理,如果要捕获多个异常,参数顺序应该是从小到大,否则编译直接报错
            System.out.println("111");
        }catch (Error error){
            System.out.println("222");
        }catch(Throwable  throwable){
            System.out.println("333");
        } finally {//善后工作,始终会被执行,一般用于资源的释放
            System.out.println("f");
        }
    }
}
throws:
throw是抛出异常,throws是往上抛异常
package Demo06;
public class Test {
    public static void main(String[] args) {
        //ctrl+alt+T
		//在Main方法中进行捕获并处理
        try {
            new Test().test(11,0);
        } catch (ArithmeticException e) {
            System.out.println("111");
        } finally {
        }
    }
    //异常如果处理不了,可以抛给下一个调用者
    public void test (int a,int b) throws ArithmeticException{
        if (b==0){
            throw new ArithmeticException();//throw关键字可直接抛出异常
        }
        System.out.println(a/b);//此处程序不会走
    }
}
自定义异常
public class MyException extends Exception{
    //判断是否大于10
    private int a;//定义一个int类型的数用来保存传入的值
    public MyException(int  a) {//构造方法给a赋值
        this.a=a;
    }
	//重写tostring
    @Override
    public String toString() {
        return "MyException{" +
                "a=" + a +
                '}';
    }
}
public class Application {
    public static void main(String[] args) {
        try {
            test(11);
        } catch (MyException e) {
            System.out.println("大于11"+e);
        }
    }
    //可抛出也可直接捕获
    static void test(int a) throws MyException {
        if (a>10){
            throw new MyException(a);
        }
            System.out.println("ok");
    }
}
本文来自博客园,作者:一只快乐的小67,转载请注明原文链接:https://www.cnblogs.com/sp520/p/15574431.html
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号