【java】java面试高频知识点2
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); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通