1、如何从现实世界中抽象出类
分析事物类—>找出类的特征(相关属性)----> 找出类的方法(分析类的方法)
2.构造方法的特点和作用是什么
特点:
-
构造方法一定与类同名
-
构造方法无返回值类型
-
构造方法可以没有(默认一个无参的构造方法),也可以有很多个构造方法
-
如果定义有有参构造函数,则无参构造函数将自动屏蔽
-
构造方法不能手动调用,在创建类实例的时候自动调用构造方法
-
构造方法不能被继承
作用:
-
给创建的对象建立一个标识符;
-
为对象数据成员开辟内存空间
-
完成对象数据成员的初始化
3.什么是默认的构造方法
-
java语言自动提供一个隐含的默认构造法
-
只要程序中已经显式定义了构造方法,那么java语言将不再提供隐含的默认构造方法。
-
那么在生成子类的实例对象时,系统将默认调用父类无参数的构造方法
4.什么是方法重载
在一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数。
要求:要求同名的方法必须有不同的参数列表,仅有返回类型不同不是不足以区分是否为重载
5.如何快速实现POJO类的封装
手动添加get、set方法或者使用Lombok这个工具简单注释代替get、set、toString方法。
6.封装的好处是什么
重用、不必关心具体的实现,是面向对象的三大特征之一、具有安全性。因为他隐藏了对象的属性和实现细节,仅使用对外公开接口,控制在程序中属性的读和修改的访问级别;将抽象得到的数据和行为(功能)相结合,形成一个有机整体。
面向对象的三大特征:封装、继承、多态
封装
-
就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
-
在Java中类中成员的属性有:public, protected, , private,这四个属性的访问权限依次降低
继承
面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
多态
多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
实现多态,有二种方式,覆盖,重载
java中实现多态需要三个条件:
1,**需要有继承关系的存在**。----》继承
2,需要有方法的重写。---------》重写
3,需要有父类的引用指向子类对象。------》向上转型
多态的转型:
向上转型:
子类引用的对象转换为父类类型称为向上转型。通俗地说就是是将子类对象转为父类对象。此处父类对象可以是接口。
注意事项:1.向上转型时,子类单独定义的方法会丢失。
2.子类引用不能指向父类对象
好处:1.减少重复代码,使代码变得简洁。
2. 提高系统扩展性。
向下转型:
向下转型是把父类对象转为子类对象
注意事项:1向下转型的前提是父类对象指向的是子类对象(也就是说,在向下转型之前,它得先向上转型)
2. 向下转型只能转型为本类对象(猫是不能变成狗的)。
7.什么是类方法?什么是类的属性?
java是面向对象的语言,一切皆为对象,对象里有属性(对象的特点和方法)
类属性:就是针对 类对象 定义的属性
- 使用 赋值语句 在 class 关键字下方可以定义 类属性
- 类属性 用于记录 与这个类相关 的特征
类方法:就是针对 类对象 定义的方法
- 在 类方法 内部可以直接访问 类属性 或者调用其他的 类方法
8. final关键字可以修饰什么?不能修饰什么?
*final关键字可以用来修饰类、方法、变量*
A、修饰类(class)。
1、该类不能被继承。
2、类中的方法不会被覆盖,因此默认都是final的。
3、用途:设计类时,如果该类不需要有子类,不必要被扩展,类的实现细节不允许被改变,那么就设计成final类
B、修饰方法(method)
1、该方法可以被继承,但是不能被覆盖。
2、用途:一个类不允许子类覆盖该方法,则用final来修饰
3、好处:可以防止继承它的子类修改该方法的意义和实现;更为高效,编译器在遇到调用fianal方法转入内嵌机制,提高了执行效率。
4、注意:父类中的private成员方法不能被子类覆盖,因此,private方法默认是final型的(可以查看编译后的class文件)
C、修饰变量(variable)
1、用final修饰后变为常量。包括静态变量、实例变量和局部变量这三种。
2、特点:可以先声明,不给初值,这种叫做final空白。但是使用前必须被初始化。一旦被赋值,将不能再被改变。
D、修饰参数(arguments)
1、用final修饰参数时,可以读取该参数,但是不能对其作出修改
final关键字不能用来抽象类和接口
9.abstract关键字可以修饰什么?不能修饰什么?
1.abstract修饰类:抽象类
1)不可被实例化
2)抽象类有构造器 (凡是类都有构造器)
3)抽象方法所在的类,一定是抽象类。
4)抽象类中可以没有抽象方法。
2.abstract修饰方法:抽象方法
1)格式:没有方法体,包括{}.如:public abstract void eat();
2)抽象方法只保留方法的功能,而具体的执行,交给继承抽象类的子类,由子类重写此抽象方法。
3)若子类继承抽象类,并重写了所有的抽象方法,则此类是一个"实体类",即可以实例化
4)若子类继承抽象类,没有重写所有的抽象方法,意味着此类中仍有抽象方法,则此类必须声明为抽象的!
abstract 不能用来修饰属性、构造器、private、final、static。
10.继承条件下构造方法的调用规则是什么?
1.如果子类的构造方法中没有通过super显示调用父类的有参构造方法,也没有通过this显示 调用自身的其他构造方法,则系统会默认先调用父类的无参构造方法。在这种情况下,有没 有“super()”语句,效果都是一样的。
2.如果子类的构造方法中通过super显示调用父类的有参构造方法,则将执行父类相应的构造 方法,而不执行父类无参构造方法。
3.如果子类的构造方法中通过this显示调用自身的其他构造方法,则在相应构造方法中应用 以上两条规则。
4.特别注意的是,如果存在多级继承关系,则在创建一个子类对象时,以上规则会多次向更 高一级父类应用,一直到执行顶级父类Object类的无参构造方法为止。
11.说出java中关于继承的相关知识点
定义:
-
就是子类继承父类的属性和行为,使得子类对象具有与父类相同的属性、相同的行为。子类可以直接 访问父类中的非私有的属性和行为。
-
只能继承父类所有的非private(私有)的属性和方法,而private成员是不能被继承的
-
Fu:父类,也叫基类、超类
Zi:子类,也叫派生类
-
继承的好处和弊端:
好处:
提高了代码的复用性(多个类相同的成员可以放到同一个类中)
提高了代码的维护性(如果方法的代码需要修改,修改一处即可)
弊端:
继承让类和类之间产生了关系,类的耦合性增强了,当父类中发生变化时子类实现也不得不跟着发生变化,削弱了子类的独立性。
12.请说出重载与重写的区别?
override(重写)
1、方法名、参数、返回值相同。
2、子类方法不能缩小父类方法的访问权限。
3、子类方法不能抛出比父类方法更多的异常(但子类方法可以不抛出异常)。
4、存在于父类和子类之间。
5、方法被定义为final不能被重写。
规则:
1)、参数列表必须完全与被重写的方法相同,否则不能称其为重写而是重载。
2)、返回的类型必须一直与被重写的方法的返回类型相同,否则不能称其为重写而是重载。
3)、访问修饰符的限制一定要大于被重写方法的访问修饰符 (public>protected>default>private)
4)、重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常
- overload(重载)
1、参数类型、个数、顺序至少有一个不相同。
2、不能重载只有返回值不同的方法名。
3、存在于父类和子类、同类中。
规则:
1)、必须具有不同的参数列表;
2)、可以有不同的返回类型,只要参数列表不同就可以了;
3)、可以有不同的访问修饰符;
4)、可以抛出不同的异常;
13.请说出关于static修饰符的相关知识点
static修饰成员方法:
static修饰的方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都必须依赖具体的对象才能够被调用。
但是要注意的是,虽然在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法/变量的。
static修饰成员变量:
static修饰的变量也称为静态变量,静态变量和非静态变量的区别是:静态变量被所有对象共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
static成员变量的初始化顺序按照定义的顺序进行初始化。
static修饰代码块:
static关键字还有一个比较重要的作用就是用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来依次执行每个static块,并且只会执行一次。
static块可以优化程序性能,是因为它的特性:只会在类被初次加载的时候执行一次。
14.请说出关于this修饰符的相关知识点?
Java有一个名为
this
的关键字。它是对类的当前实例的引用。 它只能在实例的上下文中使用。
Java 中为解决变量的命名冲突和不确定性问题,引入关键字 this 代表其所在方法的当前对象的引用:
-
1. 构造方法中指该构造器所创建的新对象; 2. 方法中指调用该方法的对象; 3. 在类本身的方法或构造器中引用该类的实例变量(全局变量)和方法。 4. this 只能用在构造器或者方法中,用于获得调用当前的构造器方法的对象引用。可以和任何的对象引用一样来处理这个this对象
15.关于super修饰符的相关知识点?
1.super是直接父类对象的引用。可以通过super来访问父类中被子类覆盖的方法或属性。
2.若是构造方法的第一行代码没有显示的调用super或者this(…);那么Java默认都会调用super();含义是调用父类无参数构造方法、这里的super可以省略
16.Object类的相关知识点
- 是 Java 类库中的一个特殊类,也是所有类的父类。 也就是说,Java 允许把任何类型的对象赋给 Object 类型的变量
- Object 类是所有对象的父类,则所有的对象都可以向 Object 进行转换,在这其中也包含了数组和接口类型,即一切的引用数据类型都可以使用 Object 进行接收。
Object 类的常用方法
方法 | 说明 |
---|---|
Object clone() | 创建与该对象的类相同的新对象 |
boolean equals(Object) | 比较两对象是否相等 |
void finalize() | 当垃圾回收器确定不存在对该对象的更多引用时,对象垃圾回收器调用该方法 |
Class getClass() | 返回一个对象运行时的实例类 |
int hashCode() | 返回该对象的散列码值 |
void notify() | 激活等待在该对象的监视器上的一个线程 |
void notifyAll() | 激活等待在该对象的监视器上的全部线程 |
String toString() | 返回该对象的字符串表示 |
void wait() | 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待 |
17.接口
接口有哪些特征:
(1)接口使用 interface关键字修饰;
(2)接口不可以实例化;
(3)实现类必须实现接口的所有方法(抽象类除外);
(4)实现类可以实现多个接口(java多继承);
(5)接口中的常量都是静态常量;
接口与抽象类之间的区别是什么:
抽象类可以有默认的方法实现完全是抽象的。 接口根本不存在方法的实现。 抽象类中可以有已经实现了的方法,也可以有被abstract修饰的方法(抽象方法),因为存在抽象方法,所以该类必须是抽象类。 但是接口要求只能包含抽象方法,抽象方法是指没有实现的方法。
18.Java集合框架的相关知识点
集合框架 :
是为表示和操作集合而规定的一种统一的标准的体系结构。**
任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法。
使用集合框架的好处
- 容量自增长;
- 提供了高性能的数据结构和算法,使编码更轻松,提高了程序速度和质量;
- 允许不同 API 之间的互操作,API之间可以来回传递集合;
- 可以方便地扩展或改写集合,提高代码复用性和可操作性。
- 通过使用JDK自带的集合类,可以降低代码维护和学习新API成本。
Iterator接口
用于遍历集合元素的接口。
修饰与类型 | 方法与描述 |
---|---|
boolean | hasNext() 如果仍有元素可以迭代,则返回true。 |
E | next() 返回迭代的下一个元素。 |
void | remove() 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。 |
每一个集合都有自己的数据结构(就是容器中存储数据的方式),都有特定的取出自己内部元素的方式。为了便于操作所有的容器,取出元素。将容器内部的取出方式按照一个统一的规则向外提供,这个规则就是Iterator接口,使得对容器的遍历操作与其具体的底层实现相隔离,达到解耦的效果。
也就说,只要通过该接口就可以取出Collection集合中的元素,至于每一个具体的容器依据自己的数据结构,如何实现的具体取出细节,这个不用关心,这样就降低了取出元素和具体集合的耦合性。
ListIterator接口
ListIterator是一个功能更加强大的迭代器, 它继承于Iterator接口,只能用于各种List类型的访问。可以通过调用listIterator()方法产生一个指向List开始处的ListIterator, 还可以调用listIterator(n)方法创建一个一开始就指向列表索引为n的元素处的ListIterator
特点
允许我们向前、向后两个方向遍历 List;
在遍历时修改 List 的元素;
遍历时获取迭代器当前游标所在位置。
修饰与类型 | 方法与描述 |
---|---|
void | add(E e)将指定的元素插入到列表(可选操作) |
boolean | hasNext() 如果此列表迭代器在前进方向还有更多的元素时,返回 true。 |
boolean | hasPrevious() 如果此列表迭代器在相反方向还有更多的元素时,返回 true。 |
E | next() 返回列表中的下一个元素和光标的位置向后推进。 |
int | nextIndex() 返回调用 next()后返回的元素索引。 |
E | previous() 返回列表中的上一个元素和光标的位置向前移动。 |
int | previousIndex() 返回调用previous() 后返回的元素索引 。 |
void | remove() 删除列表中调用next()或previous()的返回最后一个元素。 |
void | set(E e) 用指定元素替换列表中调用next()或previous()的返回最后一个元素。 |
Collection接口
所有集合类都位于java.util包下。Java的集合类主要由两个接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口,这两个接口又包含了一些子接口或实现类。
***Collection一次存一个元素,是单列集合;***
Map一次存一对元素,是双列集合。Map存储的一对元素:键–值,键(key)与值(value)间有对应(映射)关系。
-
Collection集合主要有List和Set两大接口
List:是元素有序并且可以重复的集合。 主要实现: ArrayList, LinkedList, Vector
Set: 无序(存入和取出顺序有可能不一致),不可以存储重复元素。必须保证元素唯一性。
主要实现:HashSet, TreeSet。
ArrayList | LinkedList | Vector | |
---|---|---|---|
底层实现 | 数组 | 双向链表 | 数组 |
同步性及效率 | 不同步,非线程安全,效率高,支持随机访问 | 不同步,非线程安全,效率高 | 同步,线程安全,效率低 |
特点 | 查询快,增删慢 | 查询慢,增删快 | 查询快,增删慢 |
默认容量 | 10 | / | 10 |
扩容机制 | int newCapacity = oldCapacity + (oldCapacity >> 1);//1.5 倍 | / | 2 倍 |
-
**ArrayList 和 Vector 基于数组实现,对于随机访问get和set,ArrayList优于LinkedList,因为LinkedList要移动指针。
LinkedList 不会出现扩容的问题,所以比较适合随机位置增、删。但是其基于链表实现,所以在定位时需要线性扫描,效率比较低。
当操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用ArrayList会提供比较好的性能;
当你的操作是在一列数据的前面或中间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用LinkedList了。
HashSet、TreeSet、LinkedHashSet的区别
HashSet | TreeSet | LinkedHashSet | |
---|---|---|---|
底层实现 | HashMap | 红黑树 | LinkedHashMap |
重复性 | 不允许重复 | 不允许重复 | 不允许重复 |
有无序 | 无序 | 有序,支持两种排序方式,自然排序和定制排序,其中自然排序为默认的排序方式。 | 有序,以元素插入的顺序来维护集合的链接表 |
时间复杂度 | add(),remove(),contains()方法的时间复杂度是O(1) | add(),remove(),contains()方法的时间复杂度是O(logn) | LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet,时间复杂度是 O(1)。 |
同步性 | 不同步,线程不安全 | 不同步,线程不安全 | 不同步,线程不安全 |
null值 | 允许null值 | 不支持null值,会抛出 java.lang.NullPointerException 异常。因为TreeSet应用 compareTo() 方法于各个元素来比较他们,当比较null值时会抛出 NullPointerException异常。 | 允许null值 |
比较 | equals() | compareTo() | equals() |
Map接口
Map 是一种把键对象和值对象映射的集合,它的每一个元素都包含一对键对象和值对象。 Map没有继承于Collection接口,从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。
Map 的常用实现类:HashMap、TreeMap、HashTable、LinkedHashMap、ConcurrentHashMap
HashMap | HashTable | TreeMap | |
---|---|---|---|
底层实现 | 哈希表(数组+链表) | 哈希表(数组+链表) | 红黑树 |
同步性 | 线程不同步 | 同步 | 线程不同步 |
null值 | 允许 key 和 Vale 是 null,但是只允许一个 key 为 null,且这个元素存放在哈希表 0 角标位置 | 不允许key、value 是 null | value允许为null。当未实现 Comparator 接口时,key 不可以为null当实现 Comparator 接口时,若未对 null 情况进行判断,则可能抛 NullPointerException 异常。如果针对null情况实现了,可以存入,但是却不能正常使用get()访问,只能通过遍历去访问。 |
hash | 使用hash(Object key)扰动函数对 key 的 hashCode 进行扰动后作为 hash 值 | 直接使用 key 的 hashCode() 返回值作为 hash 值 | |
容量 | 容量为 2^4 且容量一定是 2^n | 默认容量是11,不一定是 2^n | |
扩容 | 两倍,且哈希桶的下标使用 &运算代替了取模 | 2倍+1,取哈希桶下标是直接用模运算 |
Collection 和 Collections的区别
Collections是个java.util下的类,是针对集合类的一个工具类,提供一系列静态方法,实现对集合的查找、排序、替换、线程安全化(将非同步的集合转换成同步的)等操作。
Collection是个java.util下的接口,它是各种集合结构的父接口,继承于它的接口主要有Set和List,提供了关于集合的一些操作,如插入、删除、判断一个元素是否其成员、遍历等。
数组工具类 Arrays
用于操作数组对象的工具类,里面都是静态方法。
数组 -> 集合:asList方法,将数组转换成list集合。
-
String[] arr ={"abc","kk","qq"}; List<String> list =Arrays.asList(arr);//将arr数组转成list集合。 //asList转换得到的ArrayList不是java.util.ArrayList,直接抛出 UnsupportedOperationException异常. 正确操作 public static void main(String[] args) { String[] arr = {"abc", "kk", "qq"}; // 使用new ArrayList包裹一层 List<String> list = new ArrayList<>(Arrays.asList(arr)); list.add("bb"); }
集合 -> 数组:用的是Collection接口中的toArray()方法;
如果给toArray传递的指定类型的数据长度小于了集合的size,那么toArray方法,会自定再创建一个该类型的数据,长度为集合的size。
如果传递的指定的类型的数组的长度大于了集合的size,那么toArray方法,就不会创建新数组,直接使用该数组即可,并将集合中的元素存储到数组中,其他为存储元素的位置默认值null。
所以,在传递指定类型数组时,最好的方式就是指定的长度和size相等的数组。