首页 > 编程语言 >【java】java面试高频知识点2

【java】java面试高频知识点2

时间:2023-02-15 14:23:58浏览次数:39  
标签:知识点 序列化 java String 接口 泛型 高频 方法 public

1.重写重载

重写:继承时对父类的方法重写该方法内容,方法类型是不变的,即返回类型,方法名字,参数都不变。值得注意的是可以改变权限,只能提高不能降低

重载:是一个类中有多个名字相同的方法,不考虑返回类型和参数名字,只考虑参数个数和参数类型。

访问权限:
依次排下来是 public、protected、友好的、privated. 不能用protected和privated修饰类。
protected和友好的差别如下:当父类和子类不在同一个包中,子类除了会继承public修饰的函数和变量之外,还会继承protected的,但是友好的就不会了

注:友好的就是啥都不写,默认友好权限。

子类继承父类时,如果父类有无参数的构造函数会自动调用,如果没有需要在子类构造函数的第一条写super();调用其带参数的构造函数。 因为子类是不继承构造函数的。

接口中的方法一定是public abstract的,实现接口的非抽象类必须明确的写出public,因为不能降低访问权限。

接口和abstract的区别是 接口只能有常量,不能有变量;接口的所有方法都是abstract的。

内部类:内部类就是在类里面的类,其不可以申明类方法和类变量,仅供其内嵌类使用。是唯一可以被static修饰的类

2.java 序列化和反序列化

2.1 概念:

将Java对象转换成字节流用来保存或者是移动,反序列化就是将字节流转换成Java对象

2.2 实现方式:

Java对象的序列化有两种方式。

  • 是相应的对象实现了序列化接口Serializable

这个使用的比较多,对于序列化接口Serializable接口是一个空的接口,它的主要作用就是

标识这个对象时可序列化的,jre对象在传输对象的时候会进行相关的封装。这里就不做过多的介绍了。

直接看自己写的代码:

点击查看代码
import java.io.*;


public class TestSerializable implements Serializable {
    private String Name;
    private transient String sex;//加上transient就标志不会序列化了
    private static String height; //静态变量也不会被序列化


    public TestSerializable(String name, String sex) {
        Name = name;
        this.sex = sex;
    }


    public String getName() {
        return Name;
    }


    public void setName(String name) {
        Name = name;
    }


    public String getSex() {
        return sex;
    }


    public void setSex(String sex) {
        this.sex = sex;
    }


    public static String getHeight() {
        return height;
    }


    public static void setHeight(String height) {
        TestSerializable.height = height;
    }


    @Override
    public String toString() {
        return "TestSerializable{" +
                "Name='" + Name + '\'' +
                ", sex='" + sex + '\'' +
                ", height='" + height + '\'' +
                '}';
    }


    public static void main(String[] args) throws IOException, ClassNotFoundException {
        FileOutputStream fos = new FileOutputStream("Object.txt");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        TestSerializable test = new TestSerializable("张三", "男");
        oos.writeObject(test);
        oos.close();
        FileInputStream fis = new FileInputStream("Object.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);
        TestSerializable readObject = (TestSerializable)ois.readObject();
        System.out.println(readObject);
        ois.close();
    }
}
  • 实现序列化的第二种方式为实现接口Externalizable,Externlizable接口是继承了Serializable接口的

首先,我们在序列化对象的时候,由于这个类实现了Externalizable 接口,在writeExternal()方法里定义了哪些属性可以序列化,

点击查看代码
/** * 序列化操作的扩展类 */
@Override
public void writeExternal(ObjectOutput out) throws IOException {
        //增加一个新的对象
     Date date=new Date();
     out.writeObject(userName);
     out.writeObject(password);       
     out.writeObject(date);
}


/** * 反序列化的扩展类 */
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
     //注意这里的接受顺序是有限制的哦,否则的话会出错的
     // 例如上面先write的是A对象的话,那么下面先接受的也一定是A对象...
     userName=(String) in.readObject();
     password=(String) in.readObject();
     SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
     Date date=(Date)in.readObject();
     System.out.println("反序列化后的日期为:"+sdf.format(date));
}

重写了这两个方法之后,就可以使用正常的ObjectOutputStream, ObjectInputStream 将Java对象保存到文件中或者是从文件中读取到Java对象。

对于实现Java的序列化接口需要注意一下几点:
1.Java中的序列化时transient变量(告知Java该变量不可以被序列化,用于一些敏感安全考量的变量)和静态变量不会被序列
2.也是最应该注意的,如果你先序列化对象A后序列化B,那么在反序列化的时候一定记着Java规定先读到的对象 是先被序列化的对象,不要先接收对象B,那样会报错.尤其在使用上面的Externalizable的时候一定要注意读取 的先后顺序。
3.实现序列化接口的对象并不强制声明唯一的serialVersionUID,是否声明serialVersionUID对于对象序列化的向 上向下的兼容性有很大的影响。

3、泛型和不定参数

3.1 泛型应用

主要有三个:泛型类,泛型接口,泛型方法

泛型类:

//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
//在实例化泛型类时,必须指定T的具体类型
public class Generic<T>{
    //key这个成员变量的类型为T,T的类型由外部指定  
    private T key;


    public Generic(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定
        this.key = key;
    }


    public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
        return key;
    }
}

泛型的类型参数只能是类类型(包括自定义类),不能是简单类型
传入的实参类型需与泛型的类型参数类型相同

泛型接口:

//定义一个泛型接口
public interface Generator<T> {
    public T next();
}


/**
* 未传入泛型实参时,与泛型类的定义相同,在声明类的时候,需将泛型的声明也一起加到类中
* 即:class FruitGenerator<T> implements Generator<T>{
* 如果不声明泛型,如:class FruitGenerator implements Generator<T>,编译器会报错:"Unknown class"
*/
class FruitGenerator<T> implements Generator<T>{
    @Override
    public T next() {
        return null;
    }
}


/**
* 传入泛型实参时:
* 定义一个生产器实现这个接口,虽然我们只创建了一个泛型接口Generator<T>
* 但是我们可以为T传入无数个实参,形成无数种类型的Generator接口。
* 在实现类实现泛型接口时,如已将泛型类型传入实参类型,则所有使用泛型的地方都要替换成传入的实参类型
* 即:Generator<T>,public T next();中的的T都要替换成传入的String类型。
*/
public class FruitGenerator implements Generator<String> {


    private String[] fruits = new String[]{"Apple", "Banana", "Pear"};


    @Override
    public String next() {
        Random rand = new Random();
        return fruits[rand.nextInt(3)];
    }
}

泛型方法:

泛型类,是在实例化类的时候指明泛型的具体类型;泛型方法,是在调用方法的时候指明泛型的具体类型 。

/**
* 泛型方法的基本介绍
* @param tClass 传入的泛型实参
* @return T 返回值为T类型
* 说明:
*     1)public 与 返回值中间<T>非常重要,可以理解为声明此方法为泛型方法。
*     2)只有声明了<T>的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。
*     3)<T>表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。
*     4)与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。
*/
public <T> T genericMethod(Class<T> tClass)throws InstantiationException ,
  IllegalAccessException{
        T instance = tClass.newInstance();
        return instance;
}

不定参数:不定参数其实就是个传入个数组,值得注意的是:
不定参数必须是最后一个参数
只能有一个不定参数
package Indefinite_parameter;


/**
* 测试Java不定参数
*/
public class Test {
    public void display(int[] arr, int...arg) { //java 不定参数其实就是个传入个数组
        for (int i = arg[0]; i <= arg[1]; i++) {
            System.out.print(arr[i] + " ");
        }
    }


    public static void main(String[] args) {
        Test test = new Test();
        int[] arr = {1,2,3,4,5};
        test.display(arr,2,3);
    }
}

4、反射

4.1、什么是反射?

就是对于任何一个类都能通过反射知道其的方法和属性,对于任意一个对象都能够调用它的任意一个方法或属性。这个动态的过程就叫反射。

4.2、那反射的机理上怎样的呢?

类加载的时候,通过类加载器将.Class文件载入到JVM当中,将Class文件读取入内存,同时产生class对象,一个类只产生一个Class对象。

4.3、反射的使用

首先怎么获得反射类对象,一共有四种方法:

  • 类对象.getClass();
    任何数据类型(包括基本数据类型)都有一个“静态”的class属性
  • 通过Class类的静态方法:forName(String className)(常用)
package TestReflect;

import java.lang.reflect.Field;

public class Main {
    public static void main(String[] args) throws ClassNotFoundException {
        TestReflect testReflect = new TestReflect("吴承勇", 1, 1000.0);
        System.out.println();
        Class testReflectClass1 = testReflect.getClass();
        Class testReflectClass2 = TestReflect.class;
        Class testReflectClass3 = Class.forName("TestReflect.TestReflect");//包名加类名,不知道是什么可以用testReflectClass1.getName()看看
    }
}
  • 通过类名.class对象

Class c3 = User.class

  • 基本类型的包装类都有一个Type属性

Class c4 = Integer.Type;

Class类提供了四个public方法,用于获取某个类的构造方法:

Constructor getConstructor(Class[] params)根据构造函数的参数,返回一个具体的具有public属性的构造函数


Constructor getConstructors()     返回所有具有public属性的构造函数数组


Constructor getDeclaredConstructor(Class[] params)     根据构造函数的参数,返回一个具体的构造函数(不分public和非public属性)


Constructor getDeclaredConstructors()    返回该类中所有的构造函数数组(不分public和非public属性)

#constructor.newInstance()

与获取构造方法的方式相同,存在四种获取成员方法的方式。 

Method getMethod(String name, Class[] params) 根据方法名和参数,返回一个具体的具有public属性的方法


Method[] getMethods() 返回所有具有public属性的方法数组


Method getDeclaredMethod(String name, Class[] params)  根据方法名和参数,返回一个具体的方法(不分public和非public属性)


Method[] getDeclaredMethods() 返回该类中的所有的方法数组(不分public和非public属性)

#method.invoke()

存在四种获取成员属性的方法

Field getField(String name)  根据变量名,返回一个具体的具有public属性的成员变量


Field[] getFields()  返回具有public属性的成员变量的数组


field.setAccessible(true); #关闭安全检测,就可以对私有变量操作了


Field getDeclaredField(String name) 根据变量名,返回一个成员变量(不分public和非public属性)


Field[] getDelcaredFields() 返回所有成员变量组成的数组(不分public和非public属性)

4.4、反射的使用场景

场景1:
Tomcat具体加载处理细节
(1) Tomcat(App)首先读取配置文件web.xml中配置好的Servlet的子类名称
(2) Tomcat根据读取到的客户端实现的Servlet子类的类名字符串去寻找对应的字节码文件。如果找到就将其加载到内存。
(3) Tomcat通过预先设置好的Java反射处理机制解析字节码文件并创建相应的实例对象。之后调用所需要的方法。
简单的来说就是通过反射让用户填写配置文件,而不是面对源代码

场景2:

Spring框架AOP的底层,通过反射的原理,做到了一个动态代理类代理一个接口,只要是实现这个接口的类都可以代理

4.5、如何提高性能

目前知道的有两种方法:

第一种, 通过SetAccessible()方法,这个方法的源码解释如下,设置为true的时候会忽略Java语言的检查,性能可以提升很多

SomeObject someObject = new SomeObject();
Class<? extends SomeObject> cls = SomeObject.class;
Method method = cls.getDeclaredMethod("someGetMethod");
method.setAccessible(Boolean.TRUE);
String xxx = (String) method.invoke(someObject);

第二种,将获取的方法和属性保存下来,这样就不用每次都掉用了。

标签:知识点,序列化,java,String,接口,泛型,高频,方法,public
From: https://www.cnblogs.com/wcyblogs/p/17122624.html

相关文章

  • 怎样监控java进程?
    1问题怎样实现对自己编写的java程序的监控?比如说想知道:请求的tpsjvm的内存信息,线程信息线程池的使用情况等。某段代码的执行时间常用方法就是埋点,通过代理减小业务......
  • 重学Java-第七章 Java表达式、语句和块
    7.1表达式7.1.1定义 表达式是由数字、运算符、数字分组符号(括号)、自由变量和约束变量等以能求得数值的有意义排列方法所得的组合,约束变量是在表达式中已被指定数值,......
  • 重学Java-第九章 Java循环语句
    为什么要使用循环语句,例如要在控制台打印1到5,那么就是System.out.println("1");System.out.println("2");...这样就会存在以下问题:·不灵活:需求变更就需要逐行修改·......
  • 重学Java-第八章 Java条件语句
    8.1if语句8.1.1语法​ 当需要根据给定条件来决定是否执行一段代码时,就需要用到if语句了。if块仅在布尔表达式(if括号内的表达式)为true时执行。if块的结构如下:if(条......
  • java线程的interrup、tUninterruptibles.sleepUninterruptibly和sleep、wait
    参考:(1)https://blog.csdn.net/qq_36031640/article/details/116696685(2)https://blog.csdn.net/liuxiao723846/article/details/77882011一、线程的interrupted:一个......
  • javascript放在head和body的区别以及js文件加载带来的阻塞解决
    今天在看到菜鸟教程中的HTML中的Javascript脚本代码必须位于<script>与</script>标签之间。Javascript脚本代码可被放置在HTML页面的<body>和<head>部分中......
  • java File
     CreateTime--2017年10月31日10:14:24Author:Marydonjava操作File类importjava.io.File;1.创建一个文件方式一:语法:Filefile=newFile(absolutePath);说明:只传一个参数,......
  • java 下载网络图片
     java如何下载网络图片CreateTime--2017年9月30日11:18:19Author:Marydon说明:根据网络URL获取该网页上面所有的img标签并下载符合要求的所有图片所需jar包:jsoup.jarimport......
  • JAVA中的Comparable接口和自定义比较器
    Java中的自然排序自然排序定制排序自然排序TreeSet集合在存储数据时有一定的顺序,它会将一些数据进行比较,比较调用的是comparaTo()方法,该方法是在Comparable中定义的,自然排......
  • Java NIO:Buffer、Channel 和 Selector详解
    本来要一起介绍非阻塞IO和JDK7的异步IO的,不过因为之前的文章真的太长了,有点影响读者阅读,所以这里将它们放到另一篇文章中进行介绍。Buffer一个Buffer本质上是内存......