从0开始回顾Java---系列三

简介: 面向对象1、谈一谈你对面向对象的理解 ?面向过程: 一件事该怎么做,注重实现过程,以过程为中心;面向对象: 实现对象是谁,只关心怎样使用,不关心具体实现(只关心实现对象是谁,有封装、继承、多态三大特性);总结:● 面向对象是一种编程思想,早期的面向过程的思想就是一件事该怎么做,而面向对象就是一件事该由谁来做,它怎么做的我不管,我只需要调用就行。而这些是由面向对象的三大特性来实现的,三大特性就是封装、继承、多态。2、面向对象的三大特性?封装:封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法。 多态: 所谓多态就是指程序中定义的引用变量所指

面向对象


1、谈一谈你对面向对象的理解 ?


面向过程: 一件事该怎么做,注重实现过程,以过程为中心

面向对象: 实现对象是谁,只关心怎样使用,不关心具体实现(只关心实现对象是谁,有封装、继承、多态三大特性);

总结:

  • 面向对象是一种编程思想,早期的面向过程的思想就是一件事该怎么做,而面向对象就是一件事该由谁来做,它怎么做的我不管,我只需要调用就行。而这些是由面向对象的三大特性来实现的,三大特性就是封装、继承、多态。


2、面向对象的三大特性?


封装:封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法。


多态:   所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定


继承: 使代码更容易扩展,比如有学生教师,他们都有一些公用方法与属性,可以将其抽取出来定义为父类,再去继承它,复用代码,减少冗余,易于扩展

继承主要有3个要点:

  1. 子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和方法子类是无法访问,只是拥有
  2. 子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
  3. 子类可以用自己的方式实现父类的方法。

3、重载和重写的区别?


方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性

  • 重载: 发生在同一个类中方法名相同参数列表不同参数类型不同、个数不同、顺序不同),与方法返回值和访问修饰符无关,即重载的方法不能根据返回类型进行区分
  • 重写: 发生在父子类中,方法名、参数列表必须相同返回值小于等于父类,抛出的异常小于等于父类,访问修饰符大于等于父类(里氏代换原则);如果父类方法访问修饰符为private则子类中就不是重写。


4、类之间有哪些关系?

类关系

描述

权力强侧

举例

继承

父子类之间的关系:is-a

父类

小狗继承于动物

实现

接口和实现类之间的关系:can-do

接口

小狗实现了狗叫接口

组合

比聚合更强的关系:contains-a

整体

头是身体的一部分

聚合

暂时组装的关系:has-a

组装方

小狗和绳子是暂时的聚合关系

依赖

一个类用到另一个:depends-a

被依赖方

人养小狗,人依赖于小狗

关联

平等的使用关系:links-a

平等

人使用卡消费,卡可以提取人的信息


6、内部类的作用是什么,有哪些分类?


内部类可对同一包中其他类隐藏,内部类方法可以访问定义这个内部类的作用域中的数据,包括 private 数据。


内部类是一个编译器现象,与虚拟机无关。编译器会把内部类转换成常规的类文件,用 $ 分隔外部类名与内部类名,其中匿名内部类使用数字编号,虚拟机对此一无所知。

静态内部类 属于外部类,只加载一次。作用域仅在包内,可通过 外部类名.内部类名 直接访问,类内只能访问外部类所有静态属性和方法。HashMap 的 Node 节点,ReentrantLock 中的 Sync 类,ArrayList 的 SubList 都是静态内部类。内部类中还可以定义内部类,如 ThreadLoacl 静态内部类 ThreadLoaclMap 中定义了内部类 Entry。

成员内部类 属于外部类的每个对象,随对象一起加载。不可以定义静态成员和方法,可访问外部类的所有内容。

局部内部类 定义在方法内,不能声明访问修饰符,只能定义实例成员变量和实例方法,作用范围仅在声明类的代码块中。

匿名内部类 只用一次的没有名字的类,可以简化代码,创建的对象类型相当于 new 的类的子类类型。用于实现事件监听和其他回调。


7、访问权限控制符有哪些?

访问权限控制符

本类

包内

包外子类

任何地方

public

protected

×

default

×

×

private

×

×

×


8、接口和抽象类的异同?


相同 接口和抽象类对实体类进行更高层次的抽象,仅定义公共行为和特征。

区别

抽象类

接口

成员变量

无特殊要求,可以和普通类─样定义任意类型

只能是 public static final 常量

构造方法

有构造方法用于子类实例化使用

没有构造方法,不能实例化

方法

抽象类中可以做方法定义,也可以有方法实现。

有抽象方法的类一定是抽象类,在抽象类中,可以没有抽象方法。

接口只有定义,不能有方法的实现,JDK8 支持默认/静态方法,JDK9 支持私有方法

继承

单继承

多继承

9、成员变量与局部变量的区别有哪些?

  1. 从语法形式上看:成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数;成员变量可以被 public , private , static 等修饰符所修饰,而局部变量不能被访问控制修饰符及 static 所修饰;但是,成员变量和局部变量都能被 final 所修饰。
  2. 从变量在内存中的存储方式来看:如果成员变量是使用 static 修饰的,那么这个成员变量是属于类的,如果没有使用 static 修饰,这个成员变量是属于实例的,对象存于堆内存。如果局部变量类型为基本数据类型,那么存储在栈内存,如果为引用数据类型,那存放的是指向堆内存对象的引用或者是指向常量池中的地址。
  3. 从变量在内存中的生存时间上看:成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。
  4. 成员变量如果没有被赋初值,则会自动以类型的默认值而赋值(一种情况例外:被 final 修饰的成员变量也必须显式地赋值),而局部变量则不会自动赋值。

10、静态变量和实例变量的区别?静态方法、实例方法呢?

静态变量和实例变量的区别?

  • 静态变量: 是被 static 修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不管创建多少个对象,静态变量在内存中有且仅有一个副本。
  • 实例变量: 必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。静态变量可以实现让多个对象共享内存。

静态方法和实例方法有何不同?

  • 静态方法:static修饰的方法,也被称为类方法。在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。静态方法里不能访问类的非静态成员变量和方法。
  • 实例方法:依存于类的实例,需要使用"对象名.方法名"的方式调用;可以访问类的所有成员变量和方法。


11、final关键字有什么作用?

final表示不可变的意思,可用于修饰类、属性和方法:

  • 被final修饰的类不可以被继承
  • 被final修饰的方法不可以被重写
  • 被final修饰的变量不可变,被final修饰的变量必须被显式的指定初始值,还得注意的是这里的不可变指的是变量的引用不可变,不是引用指向的内容的不可变

12、final、finally、finalize的区别?

  1. final 用于修饰变量、方法和类final修饰的类不可被继承;修饰的方法不可被重写;修饰的变量不可变。
  2. finally 作为异常处理的一部分它只能在 try/catch 语句中,并且附带一个语句块表示这段语句最终一定被执行(无论是否抛出异常),经常被用在需要释放资源的情况下,System.exit (0) 可以阻断 finally 执行。
  3. finalize 是在 java.lang.Object 里定义的方法,也就是说每一个对象都有这么个方法这个方法在 gc 启动,该对象被回收的时候被调用一个对象的 finalize 方法只会被调用一次,finalize 被调用不一定会立即回收该对象,所以有可能调用 finalize 后,该对象又不需要被回收了,然后到了真正要被回收的时候,因为前面调用过一次,所以不会再次调用 finalize 了,进而产生问题,因此不推荐使用 finalize 方法。


12、浅拷贝和深拷贝的区别?

  • 浅拷贝:仅拷贝被拷贝对象的成员变量的值,也就是基本数据类型变量的值,和引用数据类型变量的地址值,而对于引用类型变量指向的堆中的对象不会拷贝。
  • 深拷贝:完全拷贝一个对象,拷贝被拷贝对象的成员变量的值,堆中的对象也会拷贝一份。

因此深拷贝是安全的,浅拷贝的话如果有引用类型,那么拷贝后对象,引用类型变量修改,会影响原对象。

浅拷贝如何实现呢?

Object类提供的clone()方法可以非常简单地实现对象的浅拷贝。

深拷贝如何实现呢?

  • 重写克隆方法:重写克隆方法,引用类型变量单独克隆,这里可能会涉及多层递归。
  • 序列化:可以先将原对象序列化,再反序列化成拷贝对象。

13、Java 创建对象有哪几种方式?

Java中有以下四种创建对象的方式:

  • new创建新对象
  • 通过反射机制
  • 采用clone机制
  • 通过序列化机制

前两者都需要显式地调用构造方法。对于clone机制,需要注意浅拷贝和深拷贝的区别,对于序列化机制需要明确其实现原理,在Java中序列化可以通过实现Externalizable或者Serializable来实现。

14、Java 按值调用还是引用调用?

按值调用指方法接收调用者提供的值按引用调用指方法接收调用者提供的变量地址。

  • Java 总是按值调用,方法得到的是所有参数值的副本,传递对象时实际上方法接收的是对象引用的副本。方法不能修改基本数据类型的参数,如果传递了一个 int 值 ,改变值不会影响实参,因为改变的是值的一个副本。
  • 可以改变对象参数的状态,但不能让对象参数引用一个新的对象。如果传递了一个 int 数组,改变数组的内容会影响实参,而改变这个参数的引用并不会让实参引用新的数组对象。


15、多态理解  

父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,然后你编译的时候不知道这个指针指向哪里,等到运行时才知道,从而去指向对应的子类或者接口具体实现的类所指向的方法。

本质上多态分两种:

  1. 编译时多态(又称静态多态)
  2. 运行时多态(又称动态多态)

重载就是编译时多态的一个例子,多态在编译时就已经确定,运行的时候调用的是确定的方法。

Java实现多态有 3 个必要条件:继承、重写和向上转型。只有满足这 3 个条件,开发人员才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而执行不同的行为。

  • 继承:在多态中必须存在有继承关系的子类和父类。
  • 重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
  • 向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才既能可以调用父类的方法,又能调用子类的方法。

实现多态的方式:

  • 方法重写:当子类继承父类并重写父类的方法时,在调用该方法时会根据对象的实际类型调用对应的方法,从而实现多态。
  • 接口实现:当一个类实现接口并实现接口中的方法时,该类可以被当做接口类型使用,在调用该接口的方法时会根据对象的实际类型调用对应的方法,从而实现多态。

16、static和final有什么区别?

static关键字可以修饰成员变量、成员方法、初始化块、内部类,被static修饰的成员是类的成员,它属于类、不属于单个对象。以下是static修饰这4种成员时表现出的特征:

  • 类变量:被static修饰的成员变量叫类变量(静态变量)。类变量属于类,它随类的信息存储在方法区,并不随对象存储在堆中,类变量可以通过类名来访问,也可以通过对象名来访问,但建议通过类名访问它。
  • 类方法:被static修饰的成员方法叫类方法(静态方法)。类方法属于类,可以通过类名访问,也可以通过对象名访问,建议通过类名访问它。
  • 静态块:被static修饰的初始化块叫静态初始化块。静态块属于类,它在类加载的时候被隐式调用一次,之后便不会被调用了。
  • 静态内部类:被static修饰的内部类叫静态内部类。静态内部类可以包含静态成员,也可以包含非静态成员。

不能访问外部类的实例成员,只能访问外部类的静态成员。外部类的所有方法、初始化块都能访问其内部定义的静态内部类。

final关键字可以修饰类、方法、变量,以下是final修饰这3种目标时表现出的特征:

  • final类:final关键字修饰的类不可以被继承。
  • final方法: final关键字修饰的方法不可以被重写。
  • final变量:final关键字修饰的变量,一旦获得了初始值,就不可以被修改。

17、Java中native方法的使用?

什么是native方法?

简单地讲,一个native 方法就是一个Java调用非Java代码的接口。该方法的实现由非java语言实现,比如C或者C++。这个特征并非java所特有,很多其它的编程语言都有这一机制,比如在C++中,你可以用extern “C”告知C++编译器去调用一个C的函数。

native方法的使用:

  1. native方法对应的实现不在当前文件,而是在其他语言(如C和C++)实现的文件中。Java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI接口调用其他语言来实现对底层的访问。  
  2. JNI是Java本机接口(Java Native interface),它是JDK的一部分。JNI允许Java代码使用以其他语言编写的代码和代码库。Invocation API(JNI的一部分)可以用来将Java虚拟机(JVM)嵌入到本机应用程序中,从而允许程序员在本机代码内部调用Java代码。
  3. JNI的书写步骤如下:
  1. 编写带有native方法的java类
  2. 使用javac编译java类
  3. 使用javah –jni来生成后缀名为.h的头文件
  4. 使用其他语言(C,C++)实现本地方法
  5. 将本地方法编写的文件生成动态链接库

对象相等判断


1、==和 equals 的区别?

== : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象(基本数据类型 ==比较的是值,引用数据类型 ==比较的是内存地址)。

equals():它的作用也是判断两个对象是否相等。但是这个“相等”一般也分两种情况:

  • 默认情况:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象,还是相当于比较内存地址。
  • 自定义情况:类覆盖了 equals() 方法。我们平时覆盖的 equals()方法一般是比较两个对象的内容是否相同,自定义了一个相等的标准,也就是两个对象的值是否相等。


2、hashCode(),equals()两种方法是什么关系?


  • 如果两个对象相等,则hashcode一定也是相同的;
  • 两个对象相等,对两个对象分别调用equals方法都返回true;
  • 两个对象有相同的hashcode值,它们也不一定是相等的;


3、为什么重写 equals 方法必须重写 hashcode 方法 ?


判断的时候先根据hashcode进行的判断,相同的情况下再根据equals()方法进行判断。如果只重写了equals方法,而不重写hashcode的方法,会造成hashcode的值不同,而equals()方法判断出来的结果为true


在Java中的一些容器中,不允许有两个完全相同的对象,插入的时候,如果判断相同则会进行覆盖。这时候如果只重写了equals()的方法,而不重写hashcode的方法,Objecthashcode是根据对象的存储地址转换而形成的一个哈希值。这时候就有可能因为没有重写hashcode方法,造成相同的对象散列到不同的位置而造成对象的不能覆盖的问题

相关文章
|
5天前
|
存储 安全 Java
从0开始回顾Java---系列七
引言 1、常见集合有哪些? Java集合类主要由两个根接口Collection和Map派生出来的,Collection派生出了三个子接口:List、Set、Queue,因此Java集合大致也可分成List、Set、Queue、Map四种接口体系。 ● List代表了有序可重复集合,可直接根据元素的索引来访问; ● Set代表无序不可重复集合,只能根据元素本身来访问; ● Queue是队列集合。 ● Map代表的是存储key-value对的集合,可根据元素的key来访问value。 2、线程安全的集合有哪些?线程不安全的呢? 线程安全的: ● Hashtable:比HashMap多了个线
|
5天前
|
JSON Java 编译器
从0开始回顾Java---系列六
IO 1、Java中IO流分为几种? 流按照不同的特点,有很多种划分方式: • 按照流的流向分,可以分为输入流和输出流; • 按照操作单元划分,可以划分为字节流和字符流; • 按照流的角色划分为节点流和处理流。 Java Io流共涉及40多个类,看上去杂乱,其实都存在一定的关联, Java I0流的40多个类都是从如下4个抽象类基类中派生出来的。 • InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。 • OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。 IO流用到了什么设计模式? 装饰器模式 2、既
|
5天前
|
存储 缓存 安全
从0开始回顾Java---系列四
String 1、String 是 Java 基本数据类型吗?可以被继承吗?为什么? String是Java基本数据类型吗? 不是。Java 中的基本数据类型只有8个:byte、short、int、long、float、double、char、boolean;除了基本类型(primitive type),剩下的都是引用类型(reference type)。 String是一个比较特殊的引用数据类型。 String 类可以继承吗? 不行。String 类使用 final 修饰,是所谓的不可变类,无法被继承。 String 类为什么要被设计成不可继承? 1. 字符串是一种非常重要且常用的数据类型
|
5天前
|
存储 安全 算法
从0开始回顾Java---系列九
TreeMap 1、TreeMap 有什么特点? 1. TreeMap是基于红黑树的一种提供顺序访问的Map,增删改查的平均和最差时间复杂度均为 O(logn) ,最大特点是 Key 有序。 2. Key 必须实现 Comparable 接口或提供的 Comparator 比较器,所以 Key 不允许为 null。 3. TreeMap是一个线程不安全,有序的键值对集合,因为TreeMap实现了SotredMap接口。 4. TreeMap实现了Cloneable接口,可被克隆,实现了Serializable接口,可序列化; 2、讲讲 TreeMap 怎么实现有序的? TreeMap
|
5天前
|
存储 安全 算法
从0开始回顾Java---系列八
HashMap 1、HashMap 有什么特点? HashMap 基于哈希表的 Map 接口实现,是以 key-value 存储形式存在,主要用来存放键值对。 特点: ● HashMap 的实现不是同步的,这意味着它不是线程安全的 ● key 是唯一不重复的,底层的哈希表结构,依赖 hashCode 方法和 equals 方法保证键的唯一 ● key、value 都可以为null,但是 key 位置只能是一个null ● HashMap 中的映射不是有序的,即存取是无序的 ● key 要存储的是自定义对象,需要重写 hashCode 和 equals 方法,防止出现地址不同内
|
5天前
|
缓存 Java 调度
从0开始回顾Java---系列五
Integer 1、Integer a= 127,Integer b = 127;Integer c= 128,Integer d = 128;相等吗? 答案是a和b相等,c和d不相等。 ● 对于基本数据类型==比较的值 ● 对于引用数据类型==比较的是地址 Integer a= 127这种赋值,是用到了Integer自动装箱的机制。自动装箱的时候会去缓存池里取Integer对象,没有取到才会创建新的对象。 如果整型字面量的值在-128到127之间,那么自动装箱时不会new新的Integer对象,而是直接引用缓存池中的Integer对象,超过范围 a1==b1的结果是false。 publi
|
Java 编译器
强哥说Java--Java基础
强哥说Java--Java基础
61 0
|
存储 Java 开发者
[Java --- List]
我们之前实现过的顺序表,只能保存 int 类型的元素,如果现在需要保存 指向 Person 类型对象的引用的顺序表,请问应该如何解决?如果又需要保存指向 Book 对象类型的引用呢?
|
Java
Java报错:Cause: java.io.NotSerializableException: xxx 解决方案
原因是实体类没有开启序列化接口导致的 开启实体类序列化接口即可:
110 0
|
Java 编译器
Java---继承
继承的基本思想是,基于已有的类创造新的类。继承已存在的类就是复用这些类的方法,而且可以增加一些新的方法和字段,使新类能够适应新的情况,继承是Java程序设计中一项核心技术,它主要解决的问题是:共性的抽取,实现代码复用。
Java---继承