Java经典知识点&面试题整理02

这一期我们继续介绍Java相关的面试题,这一次还是5道题。下面我们开始一一进行解答。

1.请简要比较接口和抽象类的区别。

①:接口中不能包含任何非抽象方法,但是抽象类可以包含

②:接口可以实现多继承,抽象类不可以实现多继承

③:抽象类要被子类继承,接口要被类实现;

④:接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量

⑤:抽象类可以有构造器,接口不能有构造器。

具体可参照博客链接https://www.cnblogs.com/jmyyyy/p/10960271.html,这里只列出常见的几种区别了。

2.(1)什么是内部类?请简要说说内部类有哪些特点?

(2)什么是静态内部类?其有什么特点?

(1)内部类就是定义在另一个类中内部的类,内部类的特点有:

①:内部类可以访问其外部类的所有属性和方法;

②:外部类无法直接访问内部类的属性和方法,需要实例化才可以;

③:内部类如果和外部类有同名的属性,优先执行内部类的属性

④:内部类不能定义static的变量。

下面我们写一个简单的例子,加深对内部类的理解。代码如下:

public class Outer {
	
	private int varOuter = 100;
	private double x = 20.5;
	
	/**
	 * 内部类:对于其他类中的类是隐藏的,不能被访问;
	 * 不能定义static的变量,
	 * 内部类可以直接访问到外部类的变量,无需实例化; 
	 * 但是外部类想要访问到内部类,需要实例化,
	 * 如果类不想被其他类使用,可以声明为内部类.
	 * 内部类如果和外部类有同名的属性,优先执行内部类的属性.
	 * @author autumn_leaf
	 *
	 */
	class Inner {
		int varInner = 200; //变量定义
		double x = 50.5;//内部变量x
		//方法定义
		public void showOuter() {
			System.out.println(varOuter);//调用外部类的变量
			System.out.println(x);//50.5
			//20.5
			System.out.println(Outer.this.x);//调用外部类的同名属性
		}
	}
	
	//外部类引用内部类必须要实例化
	public void showInner() {
		Inner i = new Inner();
		System.out.println(i.varInner);//200
		i.showOuter();//100
	}
	
	public static void main(String[] args) {
		Outer outer = new Outer();
		outer.showInner();
	}

}

(2)静态内部类就是用static标识的内部类,其特点是可以定义静态成员和非静态成员,而非静态内部类只能定义非静态成员

下面写一个小的例子来简要介绍静态内部类的用法,代码如下:

public class OuterStatic {
	
	private int varOuter = 20;
	//内部类可用修饰符:default public private protected
	/**
	 * 定义一个静态内部类,可以定义静态的变量,也可以定义非静态的变量
	 * 非静态内部类不可以定义static的变量
	 */
	private static class innerStatic {
		static int a;
		int varInner = 200;
		public void showOuter() {
			//静态内部类不能调用外部非static修饰的内容
			//System.out.println(varOuter);
			//可以调用类中定义的非静态变量
			System.out.println(varInner);
		}	
	}
		
	public static void main(String[] args) {
		//调用静态内部类
		OuterStatic.innerStatic oi = new OuterStatic.innerStatic();
		System.out.println(oi.varInner);
		System.out.println(oi.a);
		//调用非静态内部类
		Outer o = new Outer();
		Outer.Inner i = o.new Inner();
		System.out.println(i.varInner);
		i.showOuter();
	}
}

3.请简要说说final关键字的用法。

final可以修饰属性、方法以及类,其中:①被修饰的变量不能够被重新赋值,可以在声明时赋值,或者在构造器中赋值;②被修饰的类不能够被继承;③被修饰的方法不能在子类中被覆盖,即不能够被修改。下面写一个简单的例子,代码如下:

public final class FinalDemo {
	int a;//默认值为0
	static final int b = 1;//必须有值
	//如果当前不是final修饰的类,那么可能发生继承关系
	//父类被final修饰的方法,子类继承的时候,不能进行覆盖
	static final void test() {
		System.out.println("不能被修改!");
	}	
}

4.试比较Object类型与String类型equals方法的区别。

Object类型的equals方法只会比较是否是同一个对象,而String类型的equals方法优先判断是否是同一个对象,若不是同一个对象,则按位进行比较。

下面写一个简单的例子来显示刚刚的说明,代码如下:

public class ObjectSample {
	
	public static void main(String[] args) {
		String str1 = new String("haha");
		String str2 = "haha";
		String str3 = "haha";
		System.out.println(str1 == str2);//false str1进行了实例化,所以这里不是同一个对象
		System.out.println(str2 == str3);//true 指向同一个对象
		//Object类型equals方法只会比较是否是同一对象
		//String类型equals方法优先判断是否同一个对象,若不是同对象,则按位进行比较
		System.out.println(str1.equals(str2));//true
	}

}

结果我已经注释在后面了,下面我们查看一下equals方法的底层源码,如下:

 public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

5.尝试对一个邮箱进行检测并抛出异常,要求用户名长度不能超过12位(@符号前面为用户名),@符号后面必须以.com或者.cn结尾,试写出简要的检验代码。

我们首先定义一个异常EmailCheckException,代码如下:

public class EmailCheckException extends Exception{

	private static final long serialVersionUID = 1L;

	public EmailCheckException(String msg) {
		super(msg);
	}

}

然后邮箱检测类EmailCheck代码如下:

import java.util.Scanner;

/**
 *  邮箱检测
 * @author autumn_leaf
 *
 */
public class EmailCheck {
	
	public static void checkEmail(String email) throws EmailCheckException {
		int unameLen = email.indexOf('@');
		int begin = email.indexOf('@');
		int end = email.lastIndexOf('@');
		int dot = email.indexOf('.');//从开始位置.出现的位置
		//用户名长度判断
		if(unameLen > 12) {
			throw new EmailCheckException("Email用户名长度超过12位!");
		}else if(begin != end) {
			throw new EmailCheckException("Email中包含多个@!");
		}
		//未出现@或者@在开头或者@在结尾
		else if(begin == -1 || begin == 0 || begin == email.length()-1) {
			throw new EmailCheckException("@没有出现或者@位置不对!");
		}else if(begin > dot) {
			throw new EmailCheckException("@与.出现的位置不对!");
		}else if(!email.endsWith(".com") && !email.endsWith(".cn")){
			throw new EmailCheckException("邮箱结尾不是.com或者.cn!");
		}
	}

	public static void main(String[] args) {
		System.out.println("请输入邮箱:");
		Scanner sc = new Scanner(System.in);
		String email = sc.nextLine();
		try {
			checkEmail(email);
		} catch (EmailCheckException e) {
			e.printStackTrace();
		}
		System.out.println("操作结束!");
	}
}

上述代码中我们先自定义一个邮箱异常类,然后定义一个邮箱检测类,在函数中我们考虑以下几点:

①:用户名长度不能超过12;

②:只能有一个@符号;(没有或者多个@都算错)

③:@符号不能出现在第一个或者最后一个位置;

④:@必须出现在.前面;

⑤:email结尾必须以.com或者.cn结尾。

当这几点都考虑好之后,函数基本就写好了,然后我们在main方法中进行测试就行。

好了,第二期面试题分享就到这里了,我们下期再见!

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值