华清远见-重庆中心面向对象阶段总结

本文详细介绍了Java中的面向对象编程,包括类、对象、引用的定义与使用,JVM内存结构,方法的重载,构造函数,继承,多态等核心概念,并通过实例深入解析了内部类、抽象类、接口、访问控制符等特性,同时探讨了值传递与引用传递、==和equals的区别。此外,还分享了学习感悟和面试常见问题。
摘要由CSDN通过智能技术生成

1.类、对象、引用

1.1类

1.1.1类的介绍

1.类是具有相同属性和行为的对象的集合

2.类定义了该类型对象的数据结构,成为成员变量,同时还定义了一些可以被调用的功能,称为方法

3.类是用于构建对象的模板,对象的实质就是内存中的一块存储区域,其数据结构由定义它的类来决定

1.1.2类的定义 

class  类名{

   int x,y;  //成员变量 

public void  方法名(参数){
    方法要做的事情
}

}

package oopDay1;
//自定义一个用于描述点的类:Point
public class Point {
    //类的属性
    int x;   //横坐标
    int y;   //纵坐标

    //类的行为(方法)
    // 定义一个公开的无参无返回值的方法move
    public  void move(){
        y++;//纵坐标加1
    }

    public void move(int y){
        //给成员变量y赋值
        this.y=y;  //this.y是类的属性的y
    }
}

// new  Piont() 然后设置x,y的值
// Piont  p   ,p是一个Point类型的变量,然后把x,y的值传进变量中

1.1.3成员变量 

1.对象创建之后,其成员变量按照默认的方式初始化,对象成员具有初始化

成员变量的类型默认初始值
byte、short、int、long0
booleanfalse
char空白字符
引用类型null

1.2对象

1.2.1对象的介绍

1.当定义一个类之后,可以通过new 来创建该类的对象

2.对象创建的过程一般称为类的实例化

1.2.2语法规则

语法:类名 对象名= new 类名(); 

1.2.3成员变量和成员方法的调用

成员变量调用: 对象名.成员变量      

成员方法调用:对象名.方法名()   

package oopDay1;

public class TestPoint {
    public static void main(String[] args) {
        //1.创建对象
        Point p = new Point();
        //没有传数据都有它自己类型的默认值
        System.out.println("("+p.x+','+p.y+")");//(0,0)

        //2.修改对象的数据
        p.x=5;
        p.y=6;
        System.out.println("("+p.x+','+p.y+")"); //(5,6)

        //调用方法
        p.move(); //y轴向上移动1
        System.out.println("("+p.x+','+p.y+")");//(5,7)

        //调用move方法,让y移动到指定位置
        p.move(10);
    }
}

1.3引用

1.除基本8种基本数据类型外都是引用类型

2.引用类型的变量中存储的是某个对象在内存中的地址信息

3.引用类型变量声明语法:类名引用类型变量名;

4.如果要输出一个对象中的信息的话,可以通过Arrays.toString()或者在该对象的类中重写toString方法

package oopDay1;

public class TestStudent {
    public static void main(String[] args) {
        Student stu = new Student();
        System.out.println(stu);
        //stu保存的是Student对象的内存地址   包名.类名@16进制整数 oopDay1.Student@1540e19d
        //调用学生的方法
        stu.score = 88;
        stu.setName("小红");
        stu.show();
        System.out.println(stu.level());


    }
}

2.JVM内存结构

2.1方法区

方法区用于存放类的信息,Java程序运行的时候,首先通过类加载入类文件的字节码文件,经过解析后将其装入方法区,类的各种信息都在方法区保存

2.2栈内存区

栈用于存放程序运行过程中的局部变量

引用类型的变量p存储在栈内存中

2.3堆内存区

堆内存区是jvm在其内存空间开辟的一个存储空间,用于存储使用new关键字创建的对象

 3.方法的重载

3.1定义

方法的重载:方法名相同,参数不同(参数个数、参数数据类型);在一个类中可以存在多个方法名相同的方法,但是它们的参数列表必须不同;在调用方法时,会根据你传入的参数列表匹配对应的方法

package oopDay1;
//重载:
//方法同名不同参数(方法名相同,参数类型或个数必须不同)
public class Shape {
    //计算圆的面积
    public double area(int r) {
        double a = Math.PI * Math.pow(r, 2);
        return a;
    }

    //计算三角形的面积
    public double area(double bottom, double h) {
        double a = bottom * h/2;
        return a;
    }
}

3.2 this

1.可以通过this关键字表示调用该方法的对象

2.也可以使用this区分成员变量和参数

3.一个类可以创建多个对象(存储在堆中),但是方法只有一份(存储在方法区中)

4.构造函数

4.1定义构造方法

1.构造方法的名称和类名必须相同

2.构造方法没有返回值,但是不能用void修饰

4.2构造方法的重载

1.一个类可以定义多个构造方法,这些构造方法的参数列表不同

2.在创建对象时可以通过传入的参数列表找到对应的构造方法

package oopDay1;

public class Person {
    String name;
    String sex;
    int age;
    double money;

    //无参构造函数
    public Person(){
    }
    //2个参数的构造函数
    public Person(String name, String sex) {
        this.name = name;
        this.sex = sex;
    }
    //自我介绍   无参数
    public void intro() {
        System.out.println("我是" + name + ",是一个" + sex + ",我今年"
                + age + "岁,我的存款:" + money);
    }
    //早餐吃什么  有一个参数,方法调用时必须要传一个参数
    public void eat(String food) {
        System.out.println("我正在吃:" + food);
    }

}

5.继承

5.1继承的使用

1.extends关键字可以实现类的继承    子类 extends 父类;

2.子类可以继承父类的成员变量和方法,也可以定义自己的成员变量和方法;

3.一个类只能继承一父类,但是一个父类可以有多个子类,父类也可以再继承一个它的父类;

package oopDay2;

import java.util.Date;

//动物类  父类  公共属性:脚的数量 颜色 生日 性别  公共方法:叫 跑  吃
//鸡类: 属性:脚的数量 颜色 生日 性别      飞
//狗类: 属性:脚的数量 颜色 生日 性别     看门
public class Animal {
    String color;
    Date birth;
    String sex;
    int count;//脚的数量

    public void intro(Animal animal) {
        System.out.println("我是"+color+"的"+sex+"我有:"+count+"条腿,我的生日是"+birth);
    }

    public void sing(String sing){
        System.out.println("叫"+sing);
    }
    public void eat(String food){
        System.out.println("吃"+food);
    }
    public void run(){
        System.out.println("到处跑");
    }
}

class Chicken extends Animal{
    public void fly(){
        System.out.println("飞....");
    }
}

class Dog extends Animal{
    public Dog() {
    }

    public Dog(String color, Date birth, String sex, int count) {
    }

    public  void seeDoor(){
        System.out.println("看门");

    }
}

5.2向上造型

1.语法: 父类类名  对象名 =new 子类类名();

2.在使用向上造型后,子类就只能使用父类中的方法,不能使用自己的方法

5.3向下造型:

1.将父类对象类型转为子类对象类型

2.语法:跟强制类型转换差不多

父类名 父类对象名 =new 父类类名();

子类名  子类对象名=(子类名) 父类对象名;    

 5.4  instanceof关键字

1.可以指向父类的对象也可以指向它的子类型的对象;

2.可以通过instanceof判断引用指向的对象的实际类型

package oopDay2;
import java.util.Date;
public class TestAnimal {
    public static void main(String[] args) {
        Chicken c = new Chicken();
        c.color = "黄色";
        c.sex = "母鸡";
        c.birth = new Date();
        c.count = 2;
        c.fly();
        c.eat("米");
        c.run();

        //向上造型:子类对象,赋值给父类的引用
        Animal dog = new Dog("黑色", new Date(), "公狗", 4);
        //dog.seeDoor();  //编译错误,dog引用的是Animal类型,Animal没有seeDoor方法
        //如果要使用dog中的方法,需要   Dog dog = new Dog(),不能使用向上造型
        dog.eat("骨头");
        dog.run();
        dog.sing("汪汪");

        //创建Animal
        Animal a1 = new Animal();
        Animal a2 = new Chicken();
        Dog a3 = new Dog();
        //强制类型转换(父》子(向下转型))     a3是动物,本质上是狗,a3不能转为鸡这个类型
        //如果不进行类型转换,就无法使用子类中独有方法和属性
        if (a3 instanceof Dog) { //instanceof:用于判断 a3引用的对应的对象是否为Dog类型
            //a3是Dog,把a3转换为Dog,然后赋值给Dog类型的引用
            Dog dog1 = (Dog) a3;
        }

        if (a2 instanceof Chicken){
            Chicken chicken=(Chicken) a2;
            chicken.fly();
        }
    }
}

5.5继承中的构造方法

1.子类的构造方法中必须通过super调用父类的构造方法

2.子类的构造函数如果没有使用super调用父类的构造方法,Java编译器会自动加入对父类无参构造函数的调用(父类中要有无参构造方法)

package oopDay2;

public class Shape {
    int x, y;
    //构造函数
    public Shape() {
        System.out.println("shape的无参构造函数被调用");
    }
    public Shape(int x, int y) {
        this.x = x;
        this.y = y;
        System.out.println("shape的有两个参数的构造函数被调用");
    }
    //成员函数
    public double area() {
        System.out.println("shape的area函数被调用");
        return 0;
    }
}

6.方法重写 overwrite

1.子类重复类继承的方法,子类可以对其重写(方法名、参数列表、返回值必须相同)

2.子类重写父类方法后,子类对象优先调用子类自己的方法

3.子类重写父类的方法时,可以通过super调用父类的方法

class Rect extends Shape {
    double w;
    double h;
    public Rect() {
        //super();  需要写在第一行,构造器函数内部,会调用父类型的构造器函数,如果没有写super();编译器会主动添加
        System.out.println("rect的无参构造函数被调用");
    }
    public Rect(int x, int y) {
        super(x, y);
        System.out.println("rect的两个参数的构造函数被调用");
    }
    public Rect(int x, int y, double w, double h) {
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
        System.out.println("rect的两个参数的构造函数被调用");
    }
    //方法重写:在不同的类中,同名同参
    public double area() {
        System.out.println("Rect的area函数被调用");
        return w * h;
    }
}

7.关键字

7.1 package

1.定义类的时候需要指定类的名称,但是会出现命名冲突的问题

2.给类指定一个包名可以解决命名冲突问题

3.类的命名: 包名+类名

---包名可以有层次结构,一个类可以有多层包名

---公司包名命名:公司域名反写 + 项目名 + 项目模块名 + mvc模式分层

7.2 import

1.如果要在程序中,使用某个类,可以用该类的全名,这样比较复杂
  语法:java.util.Date date = new java.util.Date();
2.一般使用 import 语句导入这个类,然后使用该类
   import java . util . Date ;
  Date date = new Date ();

7.3 return:方法中的定义

1.java 中规定方法必须要指定返回值类型,如果没有返回值类型,可以使用 void 关键字
2.java 中使用 return 关键字,在方法的内部返回数据
3.定义方法的语法规则:
方法的修饰符 方法的返回值 方法的名字(方法的参数) {
       
         方法体
}
package oopDay3;

public class MethDemo {
    //计算矩形周长并返回
    public double girth(double w,double h){
        return 2*(w+h);
    }

    //计算矩形的周长,不返回
    public void girth1(double w,double h){
        System.out.println("周长:"+2 * (w + h));
    }

    public static void main(String[] args) {
        MethDemo m = new MethDemo();
        System.out.println("周长:"+m.girth(1, 2));
        m.girth1(3,5);//MethDemo类不是static,要访问其中的方法不能通过类名访问
    }
}

7.4. static

7.4.1修饰成员变量

1.用 static 修饰的成员变量不属于对象的数据结构
2.static 修饰的变量属于类的变量,通常可以通过类名来引用 static 成员
3.static 成员变量和类的信息一起存储在方法区,而不是在堆内存中
4.一个类的静态成员变量只有一份,而非静态成员对象有多份,即每个对象都有自己的非静态成员变量

7.4.2修饰成员方法

1.static 修饰的方法则不需要针对对象进行操作,其运行结构仅仅与输入的参数有关系。调用时候直接通过类名引用
2.static 修饰的方法是属于类的方法,通常用于提供工厂方法,或者工具方法
3.static 修饰的方法,调用的时候没有具体的对象,因此 static 修饰的方法不能调用非静态成员变量和成员方法
package oopDay3;

public class Cat {
    String name;
    int age;
    static  int number; //static修饰的成员变量和方法可以通过类名访问

    public  Cat(){
        number++; //new 一个猫,number就加一
    }

    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
        number++;
    }


    public static void print(){
        //静态方法:通过类名直接调用;方法的内部不能使用this;也不能使用没有static修饰的成员变量
        //非静态的方法可以通过对象调用
        //System.out.println("姓名:"+name+",年龄:"+age);
        System.out.println("当前有"+number+"只猫");
    }

    public static void main(String[] args) {
        Cat c1 = new Cat("小红", 3);
        c1.print();//number是1
        Cat.number=100;
        c1.print(); //number是100
        Cat c2 = new Cat("rose", 2);
        c2.print();//number是101


    }
}

7.5 final

7.5.1修饰类

1.final 关键字修饰的类不可以被继承
2.对于一些类,设置了 final 修饰,可以避免滥用继承造成的危害

7.5.2修饰方法

1.final 关键字修饰的方法可以不被重写
2.防止子类在定义自己的方法的时候,不经意被重写

7.5.3修饰成员变量

1.final 修饰成员变量,意为不可以改变
2.该成员变量需要在初始化的时候赋值,对象一旦创建,即该值不可以改变
package oopDay3;
//Final:修饰的类不能被继承;修饰方法不能被重写;修饰属性,赋值之后,值不可改变
public class FinalDemo {
    public static void main(String[] args) {
        Coo coo = new Coo();
        coo.print();

        int age=18;
        if (age >= Coo.MAX_AGE || age < Coo.MIN_AGE) {
            System.out.println("年龄错误");
        }else {
            System.out.println("年龄正确");
        }
        System.out.println(Math.PI);//Math类中的常量
    }

}
final class Aoo{ //final修饰的类不能被继承

}
class Boo{
    public  final void print(){
        //final修饰的方法不能被重写
        System.out.println("我是Boo中的print方法");
    }
}
class Coo extends Boo{
    int count;
    final  int size=100;  //final修饰的变量,定义的时候赋值,复制之后,值不可改变
    /*public void print(){ //编译错误,父类中的方法是final修饰的,不能被重写

    }*/

    //定义常量  用static和final修饰  ,可以通过类名调用
    static final double PI=3.14;

    //定义常量年龄,最大120,最小0
    static  final  int MAX_AGE=120;
    static final int MIN_AGE=0;
}

8.访问控制符

1.private 修饰的成员变量和方法仅仅只能在本类中调用,因此 private 修饰的内容是对内实现数据的封装,如果“ 公开 会增加维护的成本
2.public 修饰的成员变量和方法可以在任何地方调用,因此 public 修饰的内容是对外可以被调用的功
3.在定义类的时候,一般采用成员变量私有化,方法公开的原则
4.用 protected 修饰的成员变量和方法可以被子类及同一个包中的类使用
5.默认访问控制即不书写任何访问控制符,默认访问控制的成员变量和方法可以被同一个包中的类调用

修饰符本类同一个包中的类子类其他类
public可以访问可以访问可以访问可以访问
protected可以访问可以访问可以访问不能访问
默认可以访问可以访问不能访问不能访问
private可以访问不能访问不能访问不能访问

package oopDay2;

public class Cat {
    String name; //没有public ,private , protected 的修饰, 所以就是默认的访问权限。
    String sex;

    //访问权限 public>protected>默认>private
    public void catchMouse(){
        System.out.println(name+"捉老鼠");
    }
    protected  void  eat(String food){
        System.out.println(name+"吃:"+food);
    }

    private  void sing(){
        System.out.println("喵喵喵");
    }
    void  play(){
        System.out.println(name+"陪你玩");
    }
}

9.对象数组

9.1介绍

1.所谓对象数组,对象数组的元素不是基本类型,而是引用类型
2.对象数组的初始化和基本类型数组的初始化方式一样,只不过元素是对象引用而已
3.对象数组创建之后,元素的默认值是 null

9.1二维数组

1.数组的元素可以为任何类型,也包括数组类型
2.二维数组: 数组的元素如果是一个数组,那么这个数组就被称为二维数组

package oopDay3;

import java.util.Arrays;

//二维数组
public class Array2Demo {
    public static void main(String[] args) {
        //基本数据类型的二维数组
        int[][] arr=new int[5][]; //定义二维数组的时候,需要设置第一一维的长度
        arr[0]=new int[5];
        //数组的第一个元素,是一个长度为5的整形数组
        arr[1]=new int[5];
        arr[2]=new int[4];
        arr[3]=new int[4];
        arr[4]=new int[4];
        //第二维的数组长度由一维的元素来确定

        //遍历二维数组  循环的嵌套
        //把一维的元素输出在一行显示
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {//arr[i]一维的元素
                System.out.print(arr[i][j]+"\t");//arr[i][j]第二维数组中的元数
            }
            System.out.println();
        }
        System.out.println("=======================");
        //定义一个长度是5的数组,数组的元素还是一个长度为5的数组
        int[][] list=new  int[5][5];
        //遍历数组
        for (int i = 0; i < list.length; i++) {
            System.out.println(Arrays.toString(list[i]));
        }
        System.out.println("===========================");
        //二维数组初始化
        String[][] strs={{"A","B","C","D"},{"E","F","G","H"},{"H","I","J","K"}};
        for (int i = 0; i < strs.length; i++) {
            System.out.println(Arrays.toString(strs[i]));
        }

        //二维数组的赋值
        Piont[][] ps=new Piont[3][3];
        for (int i = 0; i < ps.length; i++) {
            for (int j = 0; j < ps[i].length; j++) {
                ps[i][j]= new Piont(i,j);
            }
        }
        for (int i = 0; i < ps.length; i++) {
            System.out.println(Arrays.toString(ps[i]));
        }
    }
}

10.抽象类

1.用 abstract 关键字修饰的类称之为抽象类
2.抽象类不能实例化,抽象类的意义在于 被继承
3.抽象类为子类 抽象 出公共部分,通常也定义了子类所必须实现的抽象方法
4.一个抽象类可以有抽象方法,也可以有非抽象方法
5.一个类继承了抽象类,那么必须实现父类的抽象方法,除非该类依然定义为抽象类
package oopDay3;

//abstract: 抽象 ,用于修饰类,表示这个类是一个抽象类
public abstract class Shape {
    int x;
    int y;

   /* public double area(){//实现了的方法,并不呢体现出面积的计算公式,因为这个类不太方便计算面积
        return 0;
    }*/

    public abstract double area();
    //这是一个抽象方法,需定义在抽象类里面,只是定义了方法,并没有实现方法,相当于定义了一个规范,所有Shape类型的子类,都必须实现area方法

}

class Circle extends Shape {//继承了抽象类,需要重写抽象类中的方法
    int r; //半径

    @Override
    public double area() {
        return Math.PI * r * r;
    }

}

class Rect extends Shape {
    double w;
    double h;

    @Override
    public double area() {
        return w*h;
    }
}

/*编译错误,非抽象类中不能出现抽象方法
   抽象类中可以有抽象方法,也可以没有抽象方法
   如果父类有抽象方法,子类要么重写抽象方法,要么把子类定义为抽象类
class Other{
    public abstract double area();
}*/

11.接口

11.1接口的使用

1.接口可以看成是特殊的抽象类

2.接口中只能定义常量和抽象方法

3.一个类可以同时实现多个接口,接口之间用逗号分隔开,这个类需要实现所有接口中的抽象方法

4.一个接口可以通过extends继承另一个接口,子接口继承了父接口中的定义的所有方法

package oopDay4;

//interface 接口:只能写常量的定义,抽象方法的定义
//可以通过类实现接口,然后在类中重写这些接口中定义的方法
public interface Animal {
    //定义常量
    static final String OLEDER = "女娲";

    //定义抽象方法 ,接口中的方法默认是 public abstract,可以省略
    public void eat();

    public void sleep();

    public void sing();
}
//implements 实现  类需要实现接口中的所有抽象方法
//Cat实现了Animal接口,所以Cat是Animal
class Cat implements Animal {
    String pinzgong;
    String name;

    public void catchMouse(){
        System.out.println("抓老鼠");
    }
    @Override
    public void eat() {
        System.out.println("吃");
    }

    @Override
    public void sleep() {
        System.out.println("睡");
    }

    @Override
    public void sing() {
        System.out.println("叫");
    }
}

12.内部类

12.1内部类

1.内部类:一个类定义在另一个类的内部,其所在的类成为外部类,其他类无法访问他

2.内部类一般只服务于外部类,内部类可以直接使用外部类的成员及方法

3.内部类不能独立于外部类存在,一般设置内部类为private

package oopDay4;
//内部类:类的内部包含一个其他类,这个被包含的类叫做内部类
//内部类对象的创建,需要先创建外部类对象,然后借助外部类对象创建内部类对象
//语法规则: 外部类的对象.new  内部类()  创建对象
public class Outer {
    private String name;
    private int x;
    private int y;

    public void out(){
        System.out.println("外部类的out方法");
    }

    //内部类
    class  Inner{
        String name;
        String hobby;
        //定义一个方法,用于输出外部类成员变量的值
        public void print(){
            //内部类和外部类的name重名,优先使用离自己近的
            //可以通过外部类的类名.this来访问外部类的成员变量
            System.out.println(Outer.this.name+":"+x+":"+y);
            System.out.println("内部类的成员变量"+name +hobby);
            //调用外部类的成员方法
            out();
        }
    }

    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.x=10;
        outer.y=10;
        outer.out();//调用自己类中的方法
        //Inner inner = new Inner();  //编译错误,Inner是Outer中定义的内部类
        //语法规定需要 外部类的对象.new  内部类()  创建对象
        Inner inner = outer.new Inner();
        inner.print(); //调用内部类的方法
        System.out.println("======================");
        //链式操作
        Inner inner1 = new Outer().new Inner();
        inner1.print();
    }
}

12.2静态内部类

静态内部类:使用static修饰的成员内部类,在外部类加载时存在

package oopDay4;

import javax.lang.model.element.VariableElement;

public class Outer3 {
    //静态内部类
    static  class Inner{
        public void fun(){
            System.out.println("静态内部类");
        }
    }

    public static void main(String[] args) {
        //完整写法
        Inner inner = new Inner();
        inner.fun();

        //可以直接通过new创建对象的时候访问
        new  Inner().fun();
    }
}

12.3匿名内部类

匿名内部类:在一段程序中需要创建一个类对象,创建之后就没价值了,这个类可以不用命名

  Timer timer = new Timer();
        //匿名内部类的使用
        timer.schedule(new TimerTask() {//TimerTask是一个抽象类
            @Override
            public void run() {
                System.out.println("起床了");
            }
        }, 1000, 1000);

12.4局部内部类

局部内部类:定义在方法中的类

package oopDay4;
//局部内部类:定义在方法内的一个类
public class TestInner2 {
    public void fun(){
        class Inner{
            public void fun(){
                System.out.println("局部内部类");
            }
        }
        Inner inner = new Inner();//局部内部类只能用在其所在的成员方法中
        inner.fun();//调用的是内部类的fun方法
    }

    public static void main(String[] args) {
        TestInner2 ti2 = new TestInner2();
        ti2.fun();
    }
}

13.值传递&引用传递

1.如果一个方法参数为引用类型,直接修改参数的属性值会对其造成影响

2.如果一个方法参数为引用类型,在该方法中又创建了新对象,不会对实际参数造成影响

3.如果一个方法参数为原始类型,该方法不会对实际参数造成影响

4.每一个字符串都是一个新的对象

package oopDay5;

public class Arguments {
    public static void main(String[] args) {
        Point point = new Point();
        point.x = 10;
        point.y = 10;
        point.print();//(10,10)
//        testPoint(point);//实际参数 是引用类型
//        point.print();//(11,10)
        testPoint1(point);
        point.print();//(10,10)
        String str = "你好";//创建对象,赋值给引用
        testStr(str);
        System.out.println("最后的str:" + str);
        /*输出
        * str:你好
          str:中国
          最后的str:你好
          * */
        int i = 1;
        int j = 1;
        testInt(i, j);//(10,10)
        System.out.println("最后的:(" + i + "," + j + ")");//(1,1)
    }
    public static void testPoint(Point p) {
        p.right();
    }
    public static void testPoint1(Point p) {
        p = new Point();//给引用赋值一个新的对象,不会对实际参数造成影响
        p.right();
    }
    public static void testStr(String str) {
        System.out.println("str:" + str);
        str = "中国";//每个字符串都是一个新对象
        System.out.println("str:" + str);
    }
    public static void testInt(int i, int j) {
        i = 10 * i;
        j = j * 10;
        System.out.println("(" + i + "," + j + ")");
    }
}

14.==和equals的区别

1.==:基本数据类型,判断数据值是否相等;引用类型,判断引用指向的地址是否相等

2.equals:默认是比较对象的地址是否相等;重写之后,判断对象的所有值相等

package oopDay5;

//  == :用于判断基本数据类型的数据值是否相等,用于判断引用类型的地址是否相等
// equals:用于判断对象的内存是否相等
public class EqualsDemo {
    public static void main(String[] args) {
        int a = 10;
        int b = 10;
        System.out.println(a == b);//true

        Point p1 = new Point(10, 10);
        Point p2 = new Point(10, 10);
        System.out.println(p1 == p2); //false  判断引用类型地址是否相等

        Student s1 = new Student("1001", "小红", "java2202");
        Student s2 = new Student("1001", "小红", "java2202");
        System.out.println(s1 == s2);//false
        Student s3 = s1;
        System.out.println(s3 == s1);//true 引用的是同一个对象
        System.out.println(p1.equals(p2));//false  在Point类中equals没有重写,判断的是两个对象的引用地址是否相等
        System.out.println(s1.equals(s2));//true   在Student类中重写了equals方法,判断的是值是否相等
    }


}

15.面向对象3大特性

15.1封装

1.通过private对属性修饰,提供公开的get和set方法

2.自动生成get、set方法:右键——generatealt+insert——getter and setter,选择要生成的属性

15.2继承

1.Java中是单继承,一个子类只有一个父类,一个父类可以有多个子类

15.3多态

1.对象是多种状态的

2.父类的引用指向子类的对象: Father s=new Son();

package oopDay5;

public class Printer {
    public void print(){
        System.out.println("打印机可以打印");
    }

    public static void main(String[] args) {
        //多态
        Student stu1 = new Student();
        stu1.name="tom";
        Student stu2 = new Student();
        stu2.name="jack";
        Printer p1 = new Printer3D();
        Printer p2 = new PrinterBlack();
        Printer p3 = new PrinterColor();
        p1.print();
        p2.print();
        p3.print();
    }
}
class Printer3D extends Printer{
    @Override
    public void print() {
        System.out.println("3D打印机");
    }
}
class PrinterBlack extends Printer{
    @Override
    public void print() {
        System.out.println("黑白打印机");
    }
}
class PrinterColor extends Printer{
    @Override
    public void print() {
        System.out.println("彩色打印机");
    }
}

16.静态代码块

16.1静态代码块

1.语法:  static{   代码   }

2.静态代码块在类加载时执行,只执行一次

16.2非静态代码块

1.语法:  {  代码  }

2.在创建对象时执行,每创建一个对象就要执行一次

package oopDay5;

public class CodeBlockDemo {
    private int x;
    static  double pi;
    static {//类加载完成(只加载一次),执行静态代码块
        System.out.println("静态代码块");
        pi=3.14;
    }
    {//非静态代码块,创建对象的时候,执行非静态代码块
        System.out.println("非静态代码块");
        x=10;
    }

    public CodeBlockDemo() {
        System.out.println("对象创建成功");
    }

    public static void main(String[] args) {
        CodeBlockDemo cbd1 = new CodeBlockDemo();
        CodeBlockDemo cbd2 = new CodeBlockDemo();
    }

    //成员方法
    public void add(){
        x++;
    }

    public void add(int k){
        x+=k;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof CodeBlockDemo)) return false;
        CodeBlockDemo that = (CodeBlockDemo) o;
        return x == that.x;
    }


}

17.总结

17.1感悟

我是之前学过Java面向对象的知识的,当时对子类父类的使用有一些模糊,还有接口、抽象类里面可以定义些什么也不是很清楚,经过这段时间的学习,我感觉自己对这些之前不太清楚的知识点有了更新的认识,差不多已经是全部掌握;还有就是static修饰的属性和方法的知识是掌握了的,但是在做测试题的时候没怎么注意就会出错。

17.2测试错题

1.给出下面代码, 那个语句是正确的?(   )

public class Person{
   int arr[] = new int[10];


   public static void main(String a[]) {
    System.out.println(arr[1]);
   }
}

[A]编译时将产生错误;    arr[]是非静态的,不能在静态方法里面使用

[B] 编译时正确,运行时将产生错误;

[C] 输出零; [D] 输出空;

17.3面试题

1.面向对象的特点?

---封装:使用private对属性修饰,提供公开的get、set方法

---继承:子类继承父类,子类可以使用父类中的属性和方法

---多态:对象是多种状态的

2.你怎么理解面向对象?

面向对象:侧重于创建解决事情的实体,就是把现实中的事物都抽象为“对象”。每个对象是唯一的,且都可以拥有它的属性与行为。我们就可以通过调用这些对象的方法、属性去解决问题。

3.面向对象和面向过程的区别?

---面向过程:侧重于解决问题的步骤,就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。

---面向对象:侧重于创建解决事情的实体,就是把现实中的事物都抽象为“对象”。每个对象是唯一的,且都可以拥有它的属性与行为。我们就可以通过调用这些对象的方法、属性去解决问题。

4.接口和抽象类的区别是什么 ?

---接口:使用interface修饰,只能定义常量和抽象方法,实现接口需要重写接口中所有的方法

---抽象类:使用abstract修饰,可以有非抽象方法,继承抽象类可以不用重写抽象方法(自己也为抽象类)

5.成员变量与局部变量的区别有那些 ?

---成员变量:属于类,可以被访问控制符、static等修饰;存储在堆内存中;没有初始化有默认值

局部变量:是在方法中定义的变量或方法的参数,不可以被访问控制符、static等修饰;存储在栈内存中;没有初始化没有值

6.创建一个对象用什么运算符?对象实体与对象引用有何不同?

---使用new创建对象

---对象实体:存在堆内存中,一个对象可以有多个对象引用指向它

---对象引用:存在栈内存中,一个对象引用可以指向0个或1个对象

7.什么是方法的返回值?返回值在类的方法里的作用是什么?

---返回值:是某个方法体中的代码执行后产生的结果,通过return 返回

---作用:接收结果,使得它可以用于其它操作

8.一个类的构造方法的作用是什么若一个类没有声明构造方法,该程序能正确执行吗 ?为什么?

---构造方法作用:在创建对象时进行初始化

---没有构造方法程序也能正常运行,默认有一个无参构造方法

9.构造方法有哪些特性 ?

---构造方法名和类名相同

---构造方法没有返回值,但是不能用void修饰

---一个类可以有多个构造函数,但是它们的参数列表不同

10.对象的相等与指向他们的引用相等,两者有什么不同?

---对象相等:对象存储的内容相等,表示是同一对象

---引用相等:两个引用指向的地址相等

11.在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?

---因为子类继承父类之后,获取到了父类的属性和方法,而这些在使用之前必须先初始化,所以必须先调用父类的构造函数进行内容的初始化.

12.构造、静态块、构造方法中的方法执行顺序是怎样的?

---先执行静态代码块,再执行构造代码块,最后执行构造方法

13.普通类和抽象类有哪些区别?

---抽象类:被abstract修饰,不能实例化,子类继承抽象类,需要对其所有抽象方法进行重写,如果子类也是抽象类,可以不用重写,抽象类中的普通方法和属性需要子类的对象去调用

14.抽象类能使用 final 修饰吗?

---不能,抽象类必须被继承,用final修饰后就不可被继承 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值