2.面向对象

面向对象

1、说一下你对类与对象的理解

类(class):类是具有相同属性和行为的一组对象的抽象表示。

所有具体的事物都是对象(Object),在面向对象(OOP)的世界中,一切皆为对象

类和对象的关系:
  类是对象的抽象表示(模板),对象是类的一个具体实例(Instance)

2、Java创建对象有几种方式

java中提供了以下四种创建对象的方式:

1.new创建新对象
    Student s1 = new Student("huiye",16,100.00);
    System.out.println(s1);
    //Student{name='huiye', age=16, weight=100.0}

2.通过反射机制
    2.1 使用Class对象的newInstance() 方法
          Class<Student> c = Student.class;
          Student s2 = (Student) c.newInstance();
          s2.setName("huiye");
          s2.setAge(17);
          s2.setWeight(100.00);
          System.out.println(s2);
          //Student{name='huiye', age=17, weight=100.0}

    
    2.2 通过反射先获取Constructor对象,再调用Construtor对象的newInstance()方法
          Class<Student> c = Student.class;
          Constructor<Student> constructor = c.getConstructor();
          Student s3 = constructor.newInstance();
          s3.setName("huiye");
          s3.setAge(18);
          s3.setWeight(100.00);
          System.out.println(s3);
          //Student{name='huiye', age=18, weight=100.0}


3.采用clone机制
    此方式需要实现 Cloneable 接口,重写 Object 类的 clone() 方法
    public class Student implements Cloneable{
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }

    Student s4 = new Student();
    s4.setName("huiye");
    s4.setAge(19);
    s4.setWeight(100.00);
    Object clone = s4.clone();
    System.out.println(clone);
    //Student{name='huiye', age=19, weight=100.0}

    
4.通过序列化机制
    此方式需要实现Serializable接口
    public class Student implements Serializable{}

    File file = new File("D:\\Files\\student.txt\\");
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
    Student s5 = new Student("huiye",20,100.00);
    oos.writeObject(s5);//序列化,将对象转成流,存入
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
    Student s6 = (Student) ois.readObject();//反序列化,将流读到对象中
    System.out.println(s6);
    //Student{name='huiye', age=20, weight=100.0}
什么是反射:

反射(Reflection)就是允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性。
对于⼀个已经加载的类,可以知道类的所有属性和⽅法。对于任意⼀个已经加载的对象,
可以调⽤该对象的任意⼀个属性和⽅法。
在Java虚拟机中,加载完类之后,会⽣成⼀个Class类型的对象,该对象包括了类的完整结构信息,
通过这个Class对象可以看到类的所有结构,所以称之为反射。

Java反射在实际项目中有哪些应用场景?

使用JDBC时,如果要创建数据库的连接,则需要先通过反射机制加载数据库的驱动程序;
多数框架都支持注解/XML配置,从配置中解析出来的类是字符串,需要利用反射机制实例化;
面向切面编程(AOP)的实现方案,是在程序运行时创建目标对象的代理类,这必须由反射机制来实现。
默认为浅克隆。
1、浅克隆:对当前对象进行克隆,并克隆该对象所包含的8种基本数据类型和String类型属性
  (拷贝一份该对象并重新分配内存,即产生了新的对象);
   但如果被克隆的对象中包含除8中数据类型和String类型外的其他类型的属性,
   浅克隆并不会克隆这些属性,而是指向原来对象中的属性。
2、深克隆:深克隆是在浅克隆的基础上,递归地克隆除8种基本数据类型和String类型外的属性
  (即为这些属性重新分配内存而非引用原来对象中的属性)


1、被克隆的对象的类应实现 Cloneable 接口,并重写 clone() 方法,
   在clone()方法中调用super.clone();
2、浅克隆中由于除8中数据类型和String类型外的其他类型的属性不会被克隆,
   因此当通过新对象对这些属性进行修改时,原对象的属性也会同时改变。
   而深克隆则已经对这些属性重新分配内存,所以当通过新对象对这些属性进行修改时,
   原对象的属性不会改变。

3、static关键字作用?

static是静态的意思,可以修饰属性、方法

1.属性:如果使用static来修饰属性,说明当前属性是类属性,即只存一份,并且存在类中,
  同时,此类的所有实例都可以共享

    static String country="中国";
    private static int no=0;
    可以通过类名.属性名来访问:
    Person.country="英国";

2.方法:
   2.1static修饰的方法被称为类方法,调用类方法时无须创建对象,可以通过 类名.方法名() 
       来调用 (对象名.方法名()也可)
   2.2static方法中,只能使用静态成员,不能使用非静态成员
      (非静态成员属于类,需通过调用类的方法间接使用)
   2.3static方法中,也不能使用thissuper关键字(thissuper指向对象)

    public static int plus(int a,int b){
        return a+b;
    }
    int sum=Cal.plus(1,2);

3.静态代码块
    class Person { 
        public static int total; 
        static {
            total = 100; 
        }
    }
  什么时候执行:当类被载入时,静态代码块被执行,且只被执行一次,静态块经常用来进行
  类属性的初始化

4、静态方法能否访问非静态成员,为什么?

不能

1.静态方法属于类的,非静态成员属于实例对象。

2.在类中,非静态成员不在的时候静态成员已经存在了,此时调用内存中还不存在的非静态成员,
  属于非法操作

5、访问控制符区别(封装)?

通过访问控制符限制对对象的访问
访问控制符(是否可以访问)本类中同包不同类不同包(有继承关系)不同包中(无继承关系)
private×××
default××
protected×
public
Java语言为我们提供了三种访问修饰符,即private、protected、public,在使用这些修饰符
修饰目标时,一共可以形成四种访问权限,
即private、default、protected、public,注意在不加任何修饰符时为default访问权限。

在修饰成员变量/成员方法时,该成员的四种访问权限的含义如下:
  private:该成员可以被该类内部成员访问;
  default:该成员可以被该类内部成员访问,也可以被同一包下其他的类访问;
  protected:该成员可以被该类内部成员访问,也可以被同一包下其他的类访问,还可以被它的子类
             访问;
  public:该成员可以被任意包下,任意类的成员进行访问。

在修饰类时,该类只有两种访问权限,对应的访问权限的含义如下:
  default:该类可以被同一包下其他的类访问;
  public:该类可以被任意包下,任意的类所访问。

6、面向对象三大特点?

封装、继承、多态。
封装:指的是将对象的实现细节隐藏起来,然后通过一些公用方法来暴露该对象的功能;
继承:是面向对象实现软件复用的重要手段,当子类继承父类后,子类作为一种特殊的父类,
     将直接获得父类的属性和方法;
多态:指的是子类对象可以直接赋给父类变量,但运行时依然表现出子类的行为特征,
     这意味着同一个类型的对象在执行同一个方法时,可能表现出多种行为特征。

7、什么是多态?多态实现需要满足的三个条件

多态:指的是子类对象可以直接赋给父类变量,但运行时依然表现出子类的行为特征,这意味着同一个类型
     的对象在执行同一个方法时,可能表现出多种行为特征。

多态存在的3个必要条件:
1.要有继承。
2.要有方法的重写。
3.父类引用指向子类对象(对于父类中定义的方法,如果子类中重写了该方法,
  那么父类类型的引用将会调用子类中的这个方法,这就是动态连接)

8、this关键字与super关键字区别

this:代表当前对象的引用
  this的三种用法:
    1.this.属性:区别成员变量和局部变量
    2.this.方法():调用本类的某个方法
    3.this():构造方法(只有在构造方法中 才能使用this()来调用其他的构造方法;
      this()必须放在构造方法的第一条语句中)
  this关键字只能出现在非static修饰的代码中
  
super:代表父类对象的引用
通过super关键字,在子类中,可以访问父类的成员(属性、方法、构造方法)

this()和super()都只能在构造的第一行出现,所以只能选择其一。

9、重写与重载的区别?

方法重写(override,overwrite):在子类中可以根据需要对从父类中继承来的方法进行重写;
覆盖方法必须和被覆盖方法具有相同的方法名称、参数列表、返回值类型;(返回值类型也可是子类)
覆盖方法不能使用比被覆盖方法更严格的访问权限

方法重载(overload):同一类中,方法名相同,参数列表不同的一组方法就叫重载方法
参数列表的不同主要体现在三方面:
1.数量不同
2.类型不同
3.顺序不同

10、抽象类和接口区别?

抽象类的本质是类,接口的本质是给类中的行为定制的规范或约束;

相同:抽象类与接口都可以定义抽象方法,抽象类与接口都不能被实例化;

不同:
  1.一个类只有一个父类,但一个类可同时实现多个接口;
  2.类与类之间是单继承,接口和接口之间可以是多继承;
  3.接口里只能包含抽象方法、静态方法、默认方法和私有方法,不能为普通方法提供方法实现;
    抽象类则完全可以包含普通方法;
  4.接口里只能定义静态常量,不能定义普通成员变量;抽象类里则既可以定义普通成员变量,
    也可以定义静态常量
    定义抽象类:abstract class,定义接口:interface

11、接口中可以定义哪些成员

接口中只能有 常量属性(public [static final])和 抽象方法([public abstract])(没有构造方法)
JDK8:接口中可以定义静态方法([public] static)与默认方法([public] default)
     (静态方法只能通过接口直接调用,默认方法可以通过实现类对象来调用。)
JDK9:接口中可以定义私有方法(private)与私有静态方法(private static)

12、Object类中常用方法

getClass():返回此 Object 的运行时类。
hashCode():返回该对象的哈希码值。
equals():默认比较两个对象地址是否相同,可进行覆盖,比较两个对象的内容是否相同。
toString():返回该对象的字符串表示。
clone():创建并返回此对象的一个副本。
notify():唤醒在此对象监视器上等待的单个线程。
notifyall():唤醒在此对象监视器上等待的所有线程。
wait():在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。

13、Java中会存在内存泄漏吗,请简单描述。

理论上 Java 因为有垃圾回收机制(GC)不会存在内存泄露问题;然而在实际开发中,
可能会存在无用但可达的对象,这些对象不能被 GC 回收,因此也会导致内存泄露的发生。

无用但可达:尽管短生命周期对象已经不再需要,但是长生命周期的对象持有短生命周期对象的引用

14、说明内存泄漏和内容溢出的区别和联系?

1.内存泄漏(memory leak):是指程序在申请内存后,无法释放已申请的内存空间,
          导致系统无法及时回收内存并且分配给其他进程使用。通常少次数的内存无法及时回收
          并不会给程序造成什么影响,但是如果在内存本身就比较少获取多次导致内存无法正常回收时,
          就会导致内存不够用,最终导致内存溢出。
2.内存溢出(out of memory):指程序申请内存时,没有足够的内存供申请者使用,
          导致数据无法正常存储到内存中。也就是说给你个int类型的存储数据大小的空间,
          但是却存储一个long类型的数据,这样就会导致内存溢出。

1.联系:内存泄露最终会导致内存溢出,由于系统中的内存是有限的,如果过度占用资源而不及时释放,
       最后会导致内存不足,从而无法给所需要存储的数据提供足够的内存,从而导致内存溢出。
       导致内存溢出也可能是由于在给数据分配大小时没有根据实际要求分配,
       最后导致分配的内存无法满足数据的需求,从而导致内存溢出。

2.区别:内存泄露是由于垃圾回收机制(GC)无法及时或者无法识别可以回收的数据进行及时的回收,
       导致内存的浪费;内存溢出是由于数据所需要的内存无法得到满足,导致数据无法正常存储到
       内存中。内存泄露的多次表现就是会导致内存溢出。

15、构造器(constructor)是否可被重写(override)?

构造器(构造方法)Constructor 不能被继承,因此不能重写(Override),但可以被重载(Overload)
(不同参数即可)。

16、什么是内部类?内部类有哪几个形式

可以将类的定义放在其他的类中,这种类叫内部类。
内部类一共有四种,分别是:
1.静态内部类:在类的内部定义一个static类,此类只能使用外部类的静态成员
2.成员内部类:将类的定义放在外部类的内部,此内部类可以使用外部类的非静态成员
3.方法内部类:将一个类定义在某个方法中,在此方法中就可以使用这个类来解决某些问题
4.匿名内部类:有时,我们定义了一个内部类,使用这个内部类时,只实例化一个对象,此时,
  就可以将定义类和实例化对象,两个操作合到一起,这个就是匿名内部类。使用匿名内部类的条件是,
  此类必须实现一个接口或继承一个抽象类

17、面向对象设计几大原则

1、开闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
2、里氏替换原则:任何时候都可以用子类型来替换父类型。
3、依赖倒置原则:面向接口编程,声明方法的参数类型、方法的返回类型、变量的引用类型时,
   尽可能使用抽象类型而不用具体类型,因为抽象类型可以被它的任何一个子类型所替代。
4、单一职责原则:一个类(方法)只负责一项职责。
5、接口隔离原则:建立单一接口,不要建立庞大臃肿的接口,尽量细化接口。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值