最近老是有小伙伴问类和Object相关的问题,感觉还是很多人对此不是很明白,那我们今天就干掉这两个怪物。

类介绍

Java 程序是由若干个类组成的,类也是面向对象编程思想的具体实现。

以下为类的定义:public class User {

//私有属性

private Long userId;

private String name;

private Integer age;

// 构造方法

public User() {

}

//有残构造方法

public User(Long userId, String name, Integer age) {

this.userId = userId;

this.name = name;

this.age = age;

}

//普通方法

public void say() {

System.out.println("hello world");

}

// 对外包装属性

public String getName() {

return this.name;

}

}

关键字import的三种用法

单类型导入

当我们需要使用不同包下的类时,就需要使用 import 导入包或类,这个时候才能正常使用。例如,我们要使用java.util下的 ArrayList 就必须使用 import java.util.ArrayList,代码如下:// 导入 ArrayList 类

import java.util.ArrayList;

class Test {

public static void main(String[] args) {

ArrayList list = new ArrayList();

}

}

按需类型导入

如果我们在同一个类中使用了同一个包下面的较多类时候,就会使用按需类型导入。// 用到了java.util包目录下的List、ArrayList和LinkedList类

//import java.util.ArrayList;

//import java.util.LinkedList;

//import java.util.List;

//如果不想类上有太多import,就可以直接import 包名.*

import java.util.*;

public class Test {

public static void main(String[] args) {

List list = new ArrayList<>();

List list1 = new LinkedList();

}

}

这个只是表象,其实也是一个一个的导入的,只是在代码层面看起来是一次性全部倒入了。

静态导入

import 还可以导入静态方法和静态域的功能,比如以下代码://**精准导入**

//直接导入具体的静态变量、常量、方法方法,注意导入方法直接写方法名不需要括号。

import static com.assignment.test.StaticFieldsClass.staticField;

import static com.assignment.test.StaticFieldsClass.staticFunction;

//或者使用如下形式:

//**按需导入**不必逐一指出静态成员名称的导入方式

//import static com.assignment.test.StaticFieldsClass.*;

public class StaticTest {

public static void main(String[] args) {

//这里直接写静态成员而不需要通过类名调用

System.out.println(staticField);

staticFunction();

}

}

以上代码也可以顺利的执行,这也是 import 好玩的一个地方。

构造方法

构造方法也叫构造器或构造函数,它的作用是类在进行初始化的时候会调用对应的构造方法,比如以下代码:public class User {

//私有属性

private Long userId;

private String name;

private Integer age;

// 构造方法

public User() {

}

//有参构造方法

public User(Long userId, String name, Integer age) {

this.userId = userId;

this.name = name;

this.age = age;

}

//普通方法

public void say() {

System.out.println("hello world");

}

public static void think() {

System.out.println("thinking");

}

// 对外包装属性

public String getName() {

return this.name;

}

构造方法五大原则构造方法必须与类同名;

构造方法的参数可以没有或者有多个;

构造方法不能定义返回值(默认返回类型就是本类类型);

每个类可以有一个或多个构造方法;

构造方法总是伴随着 new 操作一起使用。

注意:如果勒种没有显示的定义构造方法,那么在编译的时候回默认为其添加一个无惨构造方法。构造方法实际开发中通常都是public修饰,还有就是我们想要单例的情况下搞成private修饰。

Object

Object 类是 Java 中的一个特殊类,它是所有类的父类,Java 中的类都直接或间接的继承自 Object 类。

Object 类的常用方法如下:equals():对比两个对象是否相同

getClass():返回一个对象的运行时类

hashCode():返回该对象的哈希码值

toString():返回该对象的字符串描述

wait():使当前的线程等待

notify():唤醒在此对象监视器上等待的单个线程

notifyAll():唤醒在此对象监视器上等待的所有线程

clone():克隆一个新对象

关于更多 Object 的内容,如克隆(深克隆、浅克隆)、线程的几个常用方法wait、notify、notifyAll,对象比较,对象的hashCode值等。

继承

Java 中只支持单继承:即一个子类只能继承两个父类,而一个父类可以被多个子类继承。

每个人都只能有一个亲生父亲,一个父亲是可以有多个儿子的。

用法:使用 extends 关键字来实现类的继承,示例代码如下:class Person {

public void say() {

System.out.println("hello");

}

}

public class User extends Person {

public static void main(String[] args) {

Person user = new User();

user.say();

}

}

以上程序执行结果:hello

继承的注意点单一继承性。(在Java中是不支持多继承的,通俗的说子类只能有一个父类,而父类可以有很多子类。)

支持多层继承。(继承可以一直传下去,子类有父类,父类又有父类...)

如果父类成员使用private修饰,那么子类不能被继承。(private只是对本类有效)

如果一个子类继承了父类的属性和方法还可以有自己特有的属性和方法。(不光有父类的属性(可继承的)和方法(可继承的),也有自己独有的属性和方法。)

当子类和父类的成员变量重名的时候,子类优先。(就近原则)

继承使用技巧将公共的变量或者方法提取到超类中;

除非所有的方法都有继承的意义,否则不要使用继承;

在方法覆盖时不要改变原有方法的预期行为。

一般在写代码的时候发现代码中存在重复代码,需要向上抽取,考虑继承。

当某个类的设计非常复杂的时候可以考虑继承

继承的优点代码的可重用性。

使用继承可以轻松的定义子类。

父类的属性和方法可以用于子类中(非private修饰)。

设计应用程序变得更加简单。

设计模式中大量使用

比如:模板方法模式,就是采用继承,子类自己去实现自己的业务逻辑。

面试题

类与对象有哪些区别?

类是一个抽象的概念,是对某一事物的描述;而对象是类的实例,是实实在在存在的个体。

比如:“男人”就是一个类(一个概念),而老田(田维常)就是实实在在的一个“对象”。

注意:对象中又有类对象,即Class对象,但是类对象始终还是对象,不是类,这两个概念别搞混淆了。

Java 中可以多继承吗?

Java 中只能单继承,但可以实现多接口,并且支持多层继承。

Java 中为什么不能实现多继承?

答:从技术的实现角度来说,是为了降低编程的复杂性。假设 A 类中有一个 m() 方法,B 类中也有一个 m() 方法,如果 C 类同时继承 A 类和 B 类,那调用 C 类的 m() 方法时就会产生歧义,这无疑增加了程序开发的复杂性,为了避免这种问题的产生,Java 语言规定不能多继承类,但可以实现多接口。

覆盖和重载有哪些区别?重写(Override)从字面上看,重写就是 重新写一遍的意思。其实就是在子类中把父类本身有的方法重新写一遍。子类继承了父类原有的方法,但有时子类并不想原封不动的继承父类中的某个方法,所以在方法名,参数列表,返回类型(除过子类中方法的返回值是父类中方法返回值的子类时)都相同的情况下, 对方法体进行修改或重写,这就是重写。但要注意子类函数的访问修饰权限不能少于父类的。public class Father {

public static void main(String[] args) {

// TODO Auto-generated method stub

Son s = new Son();

s.sayHello();

}

public void sayHello() {

System.out.println("Hello");

}

}

class Son extends Father{

@Override

public void sayHello() {

// TODO Auto-generated method stub

System.out.println("hello by ");

}

}

重写 总结:

1.发生在父类与子类之间

2.方法名,参数列表,返回类型(除过子类中方法的返回类型是父类中返回类型的子类)必须相同

3.访问修饰符的限制一定要大于被重写方法的访问修饰符(public>protected>default>private)

4.重写方法一定不能抛出新的检查异常或者比被重写方法的更加宽泛的检查型异常重载(Overload)在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同甚至是参数顺序不同)则视为重载。同时,重载对返回类型没有要求,可以相同也可以不同,但不能通过返回类型是否相同来判断重载。public class Father {

public static void main(String[] args) {

// TODO Auto-generated method stub

Father s = new Father();

s.sayHello();

s.sayHello("wintershii");

}

public void sayHello() {

System.out.println("Hello");

}

public void sayHello(String name) {

System.out.println("Hello" + " " + name);

}

}

重载 总结:1.重载Overload是一个类中多态性的一种表现2.重载要求同名方法的参数列表不同(参数类型,参数个数甚至是参数顺序)3.重载的时候,返回值类型可以相同也可以不相同。无法以返回型别作为重载函数的区分标准。

为什么方法不能根据返回类型来区分重载?

答:因为在方法调用时,如果不指定类型信息,编译器就不知道你要调用哪个方法了。比如,以下代码:float max(int x,int y);

int max(int x,int y);

// 方法调用

max(1,2);

因为 max(1,2) 没有指定返回值,编译器就不知道要调用哪个方法了。

说说构造方法的特点有哪些?

答:构造方法的特征如下:构造方法必须与类名相同;

构造方法没有返回类型(默认返回本类类型);

构造方法不能被继承、覆盖、直接调用;

类定义时提供了默认的无参构造方法;

构造方法可以私有,外部无法使用私有构造方法创建对象。

构造函数能不能被覆盖?能不能被重载?

构造函数可以重载,但不能覆盖。

以下程序执行的结果是?class ExecTest {

public static void main(String[] args) {

Son son = new Son();

}

}

class Parent{

{

System.out.print("1");

}

static{

System.out.print("2");

}

public Parent(){

System.out.print("3");

}

}

class Son extends Parent{

{

System.out.print("4");

}

static{

System.out.print("5");

}

public Son(){

System.out.print("6");

}

}

结果是:251346

类加载顺序

整体

细分

以下程序执行的结果是?class A {

public int x = 0;

public static int y = 0;

public void m() {

System.out.print("A");

}

}

class B extends A {

public int x = 1;

public static int y = 2;

public void m() {

System.out.print("B");

}

public static void main(String[] args) {

A myClass = new B();

System.out.print(myClass.x);

System.out.print(myClass.y);

myClass.m();

}

}

结果是:00B

注意:在 Java 语言中,变量不能被重写。

Java 中的 this 和 super 有哪些区别?

this 和 super 都是 Java 中的关键字,起指代作用,在构造方法中必须出现在第一行,它们的区别如下。基础概念:this 是访问本类实例属性或方法;super 是子类访问父类中的属性或方法。

查找范围:this 先查本类,没有的话再查父类;super 直接访问父类。

使用:this 单独使用时,表示当前对象;super 在子类覆盖父类方法时,访问父类同名方法。

在静态方法中可以使用 this 或 super 吗?为什么?

在静态方法中不能使用 this 或 super,因为 this 和 super 指代的都是需要被创建出来的对象,而静态方法在类加载的时候就已经创建了,所以没办法在静态方法中使用 this 或 super。

静态方法的使用需要注意哪些问题?

静态方法的使用需要注意以下两个问题:静态方法中不能使用实例成员变量和实例方法;

静态方法中不能使用 this 和 super。

final 修饰符的作用有哪些?

final也是很多面试喜欢问的地方,但我觉得这个问题很无聊,通常能回答下以下5点就不错了:被final修饰的类不可以被继承

被final修饰的方法不可以被重写

被final修饰的变量不可以被改变.如果修饰引用,那么表示引用不可变,引用指向的内容可变.

被final修饰的方法,JVM会尝试将其内联,以提高运行效率

被final修饰的常量,在编译阶段会存入常量池中.

除此之外,编译器对final域要遵守的两个重排序规则更好:

在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序 初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能重排序.

经典使用场景:Integer,String等类中有使用到。

覆盖 equals() 方法的时候需要遵守哪些规则?

Oracle 官方的文档对于 equals() 重写制定的规则如下。自反性:对于任意非空的引用值 x,x.equals(x) 返回值为真。

对称性:对于任意非空的引用值 x 和 y,x.equals(y) 必须和 y.equals(x) 返回相同的结果。

传递性:对于任意的非空引用值 x、y 和 z,如果 x.equals(y) 返回值为真,y.equals(z) 返回值也为真,那么 x.equals(z) 也必须返回值为真。

一致性:对于任意非空的引用值 x 和 y,无论调用 x.equals(y) 多少次,都要返回相同的结果。在比较的过程中,对象中的数据不能被修改。

对于任意的非空引用值 x,x.equals(null) 必须返回假。

此题目不要求记忆,能知道大概即可,属于加分项题目。

在 Object 中 notify() 和 notifyAll() 方法有什么区别?

notify() 方法随机唤醒一个等待的线程,而 notifyAll() 方法将唤醒所有在等待的线程。

如何使用 clone() 方法?

如果是同一个类中使用的话,只需要实现 Cloneable 接口,定义或者处理 CloneNotSupportedException 异常即可,请参考以下代码:public class CloneTest implements Cloneable {

int num;

public static void main(String[] args) throws CloneNotSupportedException {

CloneTest ct = new CloneTest();

ct.num = 666;

System.out.println(ct.num);

CloneTest ct2 = (CloneTest) ct.clone();

System.out.println(ct2.num);

}

}

如果非内部类调用 clone() 的话,需要重写 clone() 方法,请参考以下代码:class CloneTest implements Cloneable {

int num;

public static void main(String[] args) throws CloneNotSupportedException {

CloneTest ct = new CloneTest();

ct.num = 666;

System.out.println(ct.num);

CloneTest ct2 = (CloneTest) ct.clone();

System.out.println(ct2.num);

}

@Override

protected Object clone() throws CloneNotSupportedException {

return super.clone();

}

}

public class CloneTest2 {

public static void main(String[] args) throws CloneNotSupportedException {

CloneTest ct = new CloneTest();

ct.num = 666;

System.out.println(ct.num);

CloneTest ct2 = (CloneTest) ct.clone();

System.out.println(ct2.num);

}

}

对象克隆是原型模式的经典实现。

java中对象的创建方式有哪几种?

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

通过反射机制

采用clone机制

通过序列化机制

总结

本文讲述的是一些基本的java入门知识,也顺带着讲了些稍微有点挑战的,对于还是小白的同学,有些东西不懂没事,先混个眼熟,多见几次面后,就会慢慢熟悉了,如果有机会在深入的领悟一番,那不懂的也就懂了。

每天保持学习的心态,一个月后,一年后,如果你觉得再回看之前的你,如果觉得自己当初很傻逼,那证明你进不了,如果和之前没什么两样,那证明你还是没有进步,需要反思了。

「冰冻三尺非一日之寒, 热水沸腾非一度之温」

java中怪物移动_java中两大怪物,附带面试题!相关推荐

  1. [转载]论原著中白飞飞和朱七七两大奇女子_-刘艳红-_新浪博客

    原文地址:论原著中白飞飞和朱七七两大奇女子 作者:象牙塔的乐果果 论原著中白飞飞和朱七七两大奇女子 --本评论与电视剧最多只有一分钱的关系 朱七七,白飞飞,武林外史中决不能忽视的两朵金花,两大奇女子. ...

  2. java string占用内存_Java中String到底占用多大的内存空间?

    写在前面 对于Java中的String类占用多大的内存空间这个问题,是最近面试中问的比较多的一个问题.很多小伙伴的回答的都不是很正确,有说不占空间的,有说1个字节的,有说2个字节的,有说3个字节的,有 ...

  3. java list 范围删除_JAVA中循环删除list中元素(移除list两时间范围外的元素)

    印象中循环删除list中的元素使用for循环的方式是有问题的,但是可以使用增强的for循环,然后今天在使用时发现报错了,然后去科普了一下,再然后发现这是一个误区.下面就来讲一讲..伸手党可直接跳至文末 ...

  4. java变量存储位置_java 中变量存储位置的区别

    [原文] 1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量 ...

  5. java可以多重继承吗_Java中的多重继承与组合vs继承

    java可以多重继承吗 有时我写了几篇有关Java继承,接口和组成的文章. 在这篇文章中,我们将研究多重继承,然后了解组成优于继承的好处. Java中的多重继承 多重继承是创建具有多个超类的单个类的能 ...

  6. java中有没有栈_Java中堆和栈有什么区别

    stack 和 heep 都是内存的一部分stack 空间小,速度比较快, 用来放对象的引用heep 大,一般所有创建的对象都放在这里.栈(stack):是一个先进后出的数据结构,通常用于保存方法(函 ...

  7. java 文件解析异常_java中异常的解析

    Java Exception: 1.Error 2.Runtime Exception 运行时异常 3.Exception 4.throw 用户自定义异常 异常类分两大类型:Error类代表了编译和系 ...

  8. java中socket类_Java中的Socket的用法

    Java中的Socket的用法 Java中的Socket分为普通的Socket和NioSocket. 普通Socket的用法 Java中的网络通信时通过Socket实现的,Socket分为Server ...

  9. java aes 工具类_Java中的AES加解密工具类:AESUtils

    本人手写已测试,大家可以参考使用 package com.mirana.frame.utils.encrypt; import com.mirana.frame.constants.SysConsta ...

最新文章

  1. 网页左下角蒲公英动画
  2. 自定义ConfigurationSection,创建多个嵌套的ConfigurationElementCollection节点
  3. 关于mysql的ddl_log.log文件
  4. linux tr 字符串,linux tr命令-转换或删除输入的字符的
  5. html如何复用其它页面,编写可以复用的 HTML 模板
  6. logisim输出变成红色的e_新车实拍解析 福特Mustang Mach-E亮点实拍图解
  7. figma下载_在Figma上进行原型制作的各种触发选项
  8. Matlab的parfor并行编程
  9. ubuntu下安装MySQL8.0
  10. javascript鼠标滚轮滚动实现模块的伸缩功能
  11. 解决ssh登录Host key verification failed
  12. mugen linux主程序,mugen主程序win版下载
  13. dwcs6 mysql站点_在Dreamweaver CS6中如何新建站点的方法
  14. firefox金山词霸取词
  15. 消费无人机难有新突破,行业无人机成极飞科技唯一突破口?
  16. java的栈区 堆区存放什么_简单整理java中的栈内存, 堆内存是什么?
  17. Keil MDK 编译器 AC5 和 AC6 优化选项重要内容和区别
  18. 从《我不是潘金莲》谈程序员的核心竞争力
  19. V 神打算让以太坊联姻 BCH 匿名币颤抖吗?
  20. 2020.2.26 数学函数(吃苹果问题)

热门文章

  1. 我与监控宝之间的点点滴滴
  2. hadoop源代码组织结构与阅读技巧
  3. 关于 Twing Hot Link 的一些事
  4. BCH网络升级顺利完成,将创新和开发推向新高度
  5. 从零到有的突破:BCH爱好者聚集地BCH.Club公测上线
  6. VirtualBox6.0中CentOS7.6 网络配置
  7. TCP_Wrappers 基于TCP的安全控制
  8. 这可能是最好的RxJava 2.x 入门教程(二)
  9. 第二十八条:利用有限制通配符来提升API的灵活性
  10. Ubuntu13.10下搭建emacs+sbcl+slime的lisp开发环境