多态的实现
Java实现多态有三个必要条件:继承、重写、向上转型。
继承:在多态中必须存在有继承关系的子类和父类。
重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。
只有满足了上述三个条件,我们才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而达到执行不 同的行为。
对于Java而言,它多态的实现机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用 变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。
抽象类和接口的对比
抽象类可以有构造器 接口不能有构造器
一个类最多只能继承一个抽象类 一个类可以实现多个接口
定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能 修饰抽象类
成员变量与局部变量
存储位置
成员变量:随着对象的创建而存在,随着对象的消失而消失,存储在堆内存中。
局部变量:在方法被调用,或者语句被执行的时候存在,存储在栈内存中。当方法调用完,或者语句结束后,就自动释 放。
在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?
帮助子类做初始化工作
在Java中定义一个不做事且没有参数的构造方法的作用
Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中“没有参数的构 造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用super()来调用父类中特定的 构造方法,则编译时将发生错误,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加 上一个不做事且没有参数的构造方法。
静态变量和实例变量区别
静态变量: 静态变量由于不属于任何实例对象,属于类的,所以在内存中只会有一份,在类的加载过程中,JVM只为静 态变量分配一次内存空间。 实例变量: 每次创建对象,都会为每个对象分配成员变量内存空间,实例变量是属于实例对象的,在内存中,创建几次 对象,就有几份成员变量。
内部类的分类有哪些
内部类可以分为四种:成员内部类、局部内部类、匿名内部类和静态内部类
1.静态内部类
静态内部类可以访问外部类所有的静态变量,而不可访问外部类的非静态变量;
public class Outer {
private static int radius = 1;
//静态内部类
static class StaticInner {
public void visit() {
System.out.println("visit outer static variable }:" + radius);
}
}
}
2.成员内部类
定义在类内部,成员位置上的非静态类,就是成员内部类。
public class Outer {
private static int radius = 1;
private int count = 2;
//成员内部类
class Inner {
public void visit() {
//成员内部类可以访问外部类所有的变量和方法,包括静态和非静态,私有和公有
System.out.println("visit outer static variable:" + radius);
System.out.println("visit outer variable:" + count);
}
}
public void user(){
//成员内部类依赖于外部类的实例,它的创建方式
Outer outer =new Outer();
Outer.Inner inner = outer.new Inner();
inner.visit();
}
}
3.局部内部类
定义在方法中的内部类,就是局部内部类。
局部内部类的创建方式,在对应方法内,new 内部类()
public class Outer {
private int out_a = 1;
private static int STATIC_b = 2;
public void testFunctionClass() {
int inner_c = 3;
class Inner {
private void fun() {//定义在实例方法中的局部类可以访问外部类的所有变量和方法
System.out.println(out_a);
System.out.println(STATIC_b);
System.out.println(inner_c);
}
}
Inner inner = new Inner();
inner.fun();
}
public static void testStaticFunctionClass() {
int d = 3;
class Inner {
//定义在静态方法中的局部类只能访问外部类的静态变量和方法。
private void fun() {// System.out.println(out_a); 编译错误,定义在静态方法中的局部类不可以访问外部类的实例变量
System.out.println(STATIC_b);
System.out.println(d);
}
}
Inner inner = new Inner();
inner.fun();
}
}
4.匿名内部类
匿名内部类就是没有名字的内部类,日常开发中使用的比较多
匿名内部类创建方式: new 类/接口{//匿名内部类实现部分}
特点:
匿名内部类必须继承一个抽象类或者实现一个接口。 匿名内部类不能定义任何静态成员和静态方法。 当所在的方法的形参需要被匿名内部类使用时,必须声明为 final。 匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
public class Outer {
private void test(final int i) {
new Service() {
public void method() {
for (int j = 0; j < i; j++) {
System.out.println("匿名内部类");
}
}
}.method();
}
}
interface Service{
void method();
}
异常
Error:是程序中无法处理的错误,表示运行应用程序中出现了严重的错误。此类错误一般表示代码运行时JVM出现问题。通常有Virtual MachineError(虚拟机运行错误)、NoClassDefFoundError(类定义错误)等。比如说当jvm耗完可用内存时,将出现OutOfMemoryError。此类错误发生时,JVM将终止线程。非代码性错误。因此,当此类错误发生时,应用不应该去处理此类错误。
Exception::程序本身可以捕获并且可以处理的异常。
运行时异常(不受检异常):RuntimeException类极其子类表示JVM在运行期间可能出现的错误。编译器不会检查此类异常,并且不要求处理异常,比如用空值对象的引用(NullPointerException)、数组下标越界(ArrayIndexOutBoundException)。此类异常属于不可查异常,一般是由程序逻辑错误引起的,在程序中可以选择捕获处理,也可以不处理。
非运行时异常(受检异常):Exception中除RuntimeException极其子类之外的异常。编译器会检查此类异常,如果程序中出现此类异常,比如说IOException,必须对该异常进行处理,要么使用try-catch捕获,要么使用throws语句抛出,否则编译不通过。
反射
什么是反射机制?
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调 用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Java获取反射的三种方法 1.通过new对象实现反射机制 2.通过路径实现反射机制 3.通过类名实现反射机制
网络编程
网络编程面试题(2020最新版)_ThinkWon的博客-CSDN博客_网络编程面试题
int 和 Integer
对于对象引用类型:==比较的是对象的内存地址。 对于基本数据类型:==比较的是值。 如果整型字面量的值在-128到127之间,那么自动装箱时不会new新的Integer对象,而是直接引用常量池中的Integer 对象,超过范围 a1==b1的结果是false
Integer a = new Integer(3);
Integer b = 3;// 将3自动装箱成Integer类型
int c = 3;
System.out.println(a == b);// false 两个引用没有引用同一对象
System.out.println(a == c);// true a自动拆箱成int类型再和c比较
System.out.println(b == c);// true
Integer a1 =128;
Integer b1 =128;
System.out.println(a1 == b1);// false
Integer a2 = 127;
Integer b2 = 127;
System.out.println(a2 == b2);// true
帮助文档生成:
io流
1.字节流 都可以输入或输出 父类:InputStream OutputStream
2.字符流 只能操作txt格式文件 父类:Reader Writer
FileInputStream
File file = new File("D:\\environment\\文档\\面试\\面试题\\1.txt");//比喻水厂
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(file);//比喻管道
int le = 0;
while((le=fileInputStream.read())!=-1){//比喻开水龙头
System.out.print((char)le);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if(fileInputStream!=null){
try {
fileInputStream.close();//关闭管道
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileOutputStream
try {
String writeinfo = "write info";
File file = new File("D:\\environment\\文档\\面试\\面试题\\2.txt");//自动创建文件
FileOutputStream fileOutputStream = new FileOutputStream(file);
//FileOutputStream fileOutputStream = new FileOutputStream(file,true); 追加
fileOutputStream.write(writeinfo.getBytes());//覆盖之前信息
fileOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
通过字节流实现文件复制
public static void main(String[] args) {
try {
File file = new File("D:\\environment\\文档\\面试\\面试题\\1.txt");
FileInputStream fileInputStream = new FileInputStream(file);
FileOutputStream fileOutputStream = new FileOutputStream("D:\\environment\\文档\\面试\\面试题\\2.txt");
int leg = 0;
while((leg = fileInputStream.read())>-1){
fileOutputStream.write(leg);
}
fileInputStream.close();
fileOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
BufferedInputStream
public static void main(String[] args) {
try {
FileInputStream fileInputStream = new FileInputStream("D:\\environment\\文档\\面试\\面试题\\1.txt");
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
byte[] bytes = new byte[1024];
int len = 0;
// while ((len=bufferedInputStream.read(bytes)) != -1){
// System.out.println(len);//5 按照1024字节读,返回每次读取字节数
// }
while ((len=bufferedInputStream.read()) != -1){
System.out.print(len+",");//49,50,97,115,100, 每次读取一个字节,返回字节码
}
bufferedInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
BufferedOutputStream
try {
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("D:\\environment\\文档\\面试\\面试题\\1.txt"));
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("D:\\environment\\文档\\面试\\面试题\\3.txt"));
byte[] bytes = new byte[1024];
int len = 0;
while((len=bufferedInputStream.read(bytes))!=-1){
bufferedOutputStream.write(bytes,0,len);//将指定byte数组中从偏移量off开始的len个字节写入此缓冲的输出流
}
bufferedInputStream.close();
bufferedOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
FileReader 和 BufferedReader
try {
FileReader fileReader = new FileReader("D:\\environment\\文档\\面试\\面试题\\1.txt");
char[] chars = new char[1024];
int len = 0;
while((len = fileReader.read(chars))!=-1){
System.out.println(new String(chars));
}
fileReader.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new FileReader("D:\\environment\\文档\\面试\\面试题\\1.txt"));
int len1 = 0;
char[] chars1 = new char[1024];
while ((len1=reader.read(chars1))!=-1){
System.out.println(new String(chars1));
}
} catch (Exception e) {
e.printStackTrace();
}
FileWrite BufferedWrite
try {
FileWriter fileWriter = new FileWriter("D:\\environment\\文档\\面试\\面试题\\4.txt");
fileWriter.write("filewrite写入");
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
bufferedWriter.write("bufferedwrite写入");
bufferedWriter.close();
fileWriter.close();
} catch (Exception e) {
e.printStackTrace();
}
有中文使用字符流
buffer可以加下面四个组成 , bufferinputstream bufferwriter
文件类FIle
基本方法
package com.test.io;
import java.io.File;
import java.io.IOException;
public class Testio {
public static void main(String[] args) {
try {
File file = new File("D:\\environment\\文档\\面试\\面试题\\1.txt");
file.createNewFile();//创建文件 如果该文件存在就不会再创建
File file1 = new File("D:\\environment\\文档\\面试\\面试题\\文件夹");
file1.mkdir();//创建文件夹
File file2 = new File("D:\\environment\\文档\\面试\\面试题\\文件夹\\文件夹");
file2.mkdirs();//创建文件夹
File file3 = new File("D:\\environment\\文档\\面试\\面试题\\文件夹");
file3.delete();//删除
boolean exists = file3.exists();//判断是否存在
long length = file.length();//文件大小
String name = file.getName();//文件名字
boolean directory = file.isDirectory();//是否是文件夹
File[] files = file.listFiles();//获取文件夹下所有文件或者文件夹 可以使用递归获取文件夹中所有文件
String absolutePath = file.getAbsolutePath();//绝对路径
System.out.println(length);
System.out.println(name);
System.out.println(absolutePath);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Scanner
public class Demo01 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);//属性in: public final static InputStream in = null;
String next = scanner.next();//用来接收控制台录入的字符串
System.out.println(next);
}
}
数组和集合区别
- 数组声明了它容纳的元素的类型,而集合不声明。
- 数组是静态的,一个数组实例具有固定的大小,一旦创建了就无法改变容量了。而集合是可以动态扩展容量,可以根据需要动态改变大小,集合提供更多的成员方法,能满足更多的需求。
- 数组的存放的类型只能是一种(基本类型/引用类型),集合存放的类型可以不是一种(不加泛型时添加的类型是Object)。
- 数组是java语言中内置的数据类型,是线性排列的,执行效率或者类型检查都是最快的。