java面试题07

1.重载和重写的区别?

重载(Overload):
(1)方法重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在,具有不同的参数个数/类型。重载Overloading是一个类中多态性的一种表现。
(2)Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义。调用方法时通过传递给它们的不同参数个数和参数类型来决定具体使用哪个方法, 这就是多态性。
(3)重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同也可以不相同。无法以返回型别作为重载函数的区分标准。
重写(Override):
(1)父类与子类之间的多态性,对父类的函数进行重新定义。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。在Java中,子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。方法重写又称方法覆盖。
(2)若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。
(3)子类函数的访问修饰权限不能小于父类的
重写方法的规则:
1.参数列表必须完全与被重写的方法的相同,否则不能称其为重写而是重载.
2.返回的类型必须一直与被重写的方法的返回类型相同,否则不能称其为重写而是重载.
3.访问修饰符的限制一定要大于被重写方法的访问修饰符(public>protected>default>private)
4.重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常.例如,
父类的一个方法申明了一个检查异常IOException,在重写这个方法是就不能抛出Exception,只能抛出IOException的子类异常,可以抛出非检查异常.

而重载的规则:
1.必须具有不同的参数列表;
2.可以有不同的返回类型,只要参数列表不同就可以了;
3.可以有不同的访问修饰符;
4.可以抛出不同的异常;

重写和重载的区别在于:
重写多态性起作用,对调用被重载过的方法可以大大减少代码的输入量,同一个方法名只要往里面传递不同的参数就可以拥有不同的功能或返回值.
用好重写和重载可以设计一个结构清晰而简洁的类,可以说重写和重载在编写代码过程中的作用非同一般.
Overloaded的方法是可以改变返回值的类型

 

2.聊聊多态和面向接口编程?

01.多态
011.什么是多态

面向对象的三大特性:封装、继承、多态。从一定角度来看,封装和继承几乎都是为多态而准备的。这是我们最后一个概念,也是最重要的知识点。
多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。
多态的作用:消除类型之间的耦合关系。
现实中,关于多态的例子不胜枚举。比方说按下 F1 键这个动作,如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;如果当前在 Word 下弹出的就是 Word 帮助;在 Windows 下弹出的就是 Windows 帮助和支持。同一个事件发生在不同的对象上会产生不同的结果。
下面是多态存在的三个必要条件,要求大家做梦时都能背出来!

012.多态存在的三个必要条件
001.要有继承;
002.要有重写;
003.父类引用指向子类对象。

013.多态的好处:

001.可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。
002.可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。
003.接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。如图8.3 所示。图中超类Shape规定了两个实现多态的接口方法,computeArea()以及computeVolume()。子类,如Circle和Sphere为了实现多态,完善或者覆盖这两个接口方法。
004.灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
005.简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。


014.Java中多态的实现方式:

接口实现,继承父类进行方法重写,同一个类中进行方法重载。

 


02.面向接口编程

在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的。在这种情况下,各个对象内部是如何实现自己的,对系统设计人员来讲就不那么重要了;而各个对象之间的协作关系则成为系统设计的关键。小到不同类之间的通信,大到各模块之间的交互,在系统设计之初都是要着重考虑的,这也是系统设计的主要工作内容。面向接口编程就是指按照这种思想来编程。
03.一个多态的面试题?
public class A {

public String show(D d) {
return " A and D";
}

public String show(A a) {
return " A and A";
}
}

 

public class B extends A {

public String show(B b) {
return " B and B";
}

public String show(A a) {
return " B and A";
}
}


public class C extends B {

}

public class D extends B {

}


public class Test {
public static void main(String[] args) {
A a1 = new A();
A a2 = new B(); // 父类的引用 指向了 子类的对象
B b = new B();
C c = new C();
D d = new D();

System.out.println(a1.show(b));// A and A
System.out.println(a1.show(c));// A and A
System.out.println(a1.show(d));// A and D
// 多态
System.out.println(a2.show(b));// B and A
System.out.println(a2.show(c));// B and A
System.out.println(a2.show(d));// A and D

System.out.println(b.show(b));// B and B
System.out.println(b.show(c));// B and B
System.out.println(b.show(d)); // B类中没有方法 回去 父类中查询 有没有对应的方法A and D
}
}

 

 

3.final,finally,finalize方法的区别?

01.final:关键字,可以用来修饰类,方法,和变量。
001.final修饰的类,不可以被继承。其中所有的方法都不能被重写,所以不能同时用abstract和final修饰类(abstract修饰的类是抽象类,抽象类是用于被子类继承的,和final起相反的作用);
002.final修饰的方法,不可以被重写,但是子类可以用父类中final修饰的方法。
003.Final修饰的成员变量是不可变的,如果成员变量是基本数据类型,初始化之后成员变量的值不能被改变,如果成员变量是引用类型,那么它只能指向初始化时指向的那个对象,不能再指向别的对象,但是对象当中的内容是允许改变的。
02.Finally通常和try catch搭配使用,保证不管有没有发生异常,最后都要走finally,一般都把释放连接、关闭IO流放在finally块里。
03.Finalize是object类中的一个方法,子类可以重写finalize()方法实现对资源的回收。垃圾回收只负责回收内存,并不负责资源的回收,资源回收要由程序员完成,Java虚拟机在垃圾回收之前会先调用垃圾对象的finalize方法用于使对象释放资源(如关闭连接、关闭文件),之后才进行垃圾回收,这个方法一般不会显示的调用,在垃圾回收时垃圾回收器会主动调用。

 

4.StringBuffer和StringBuilder的区别?

01.String是一个不可变的对象,每次对String类型的字符串进行改变时就相当于生成了一个新的String对象。

其底层为: private final char value[];所以是不可变对象。

02.StringBuffer和StringBuilder都继承了AbstractStringBuilder,而StringBuffer大部分方法都是synchronized,也就是线程安全的,

而StringBuilder就没有,所以,我们查看API可以知道,StringBuilder可以操作StringBuffer,但是StringBuffer不可以操作StringBuilder,这也是线程的原因;

 

所以,可想而知,StringBuffer的效率肯定没有StringBuilder,因为StringBuffer要维持同步锁,这肯定要消耗部分资源

03.执行效率:StringBuilder>StringBuffer>String,所以,如果这是考虑单线程程序的话,用StringBuilder,如果涉及到多线程的,那只能是StringBuffer。

 

5.java中,反射机制的基本原理?Class类的作用?

01.反射的概念:
在Java中的反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个类,都能调用它的任意一个方法;
这种动态获取信息以及动态调用对象的功能成为Java语言的反射机制。
02.反射能实现的功能:
001. 在运行时判断任意一个对象所属的类
002. 在运行时构造任意一个类的对象
003. 在运行时判断任意一个类所具有的方法和属性
004. 在运行时调用任意一个对象的方法
005. 生成动态代理
在动态代理中应用的反射最多,可也说有动态代理必有反射。

 

6.堆区和栈区的区别?

堆和栈都是Java的内存空间,用于存储信息;

堆用于存储变量名;栈用于存储变量的值或引用;

 

7.手写出jdbc连接mysql/oracle数据库,并进行查询的典型做法?

01.实体类:
package cn.pb.bean;

/**
* student的实体类
*/
public class Student {

private int sid;
private int age;
private String sname;

public Student(int sid, int age, String sname) {
this.sid = sid;
this.age = age;
this.sname = sname;
}

public Student(int age, String sname) {
this.age = age;
this.sname = sname;
}

public Student() {

}

public int getSid() {
return sid;
}

public void setSid(int sid) {
this.sid = sid;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getSname() {
return sname;
}

public void setSname(String sname) {
this.sname = sname;
}

@Override
public String toString() {
return "Student{" +
"sid=" + sid +
", age=" + age +
", sname='" + sname + '\'' +
'}';
}
}
02.普通方式连接数据库:
public void TestJdbc(){
/**
* 连接数据库的四要素
*/
String driver="com.mysql.jdbc.Driver";
String url="jdbc:mysql://localhost:3306/spring";
String username="root";
String password="666888";
/**
* 创建jdbc需要的api
*/
Connection connection=null;
PreparedStatement pst=null;
ResultSet rs=null;

 

try {
//01加载驱动
Class.forName(driver);
//02获取链接
connection= DriverManager.getConnection(url, username, password);
//03书写sql语句
String sql="select sid,sname,age from student where sid=?";
//04给参数赋值
pst=connection.prepareStatement(sql);
pst.setInt(1,2);
//05获取查询结果
rs=pst.executeQuery();

while(rs.next()){
Student student=new Student();
student.setSid(rs.getInt("sid"));
student.setAge(rs.getInt("age"));
student.setSname(rs.getString("sname"));
System.out.println(student);
}

} catch (Exception e) {
e.printStackTrace();
}finally{
try {
rs.close();
pst.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}

}
03.使用反射机制来 动态的给 Student对象赋值
/**
* 我们使用反射机制来 动态的给 Student对象赋值
*/
public static void main(String[] args){
/**
* 连接数据库的四要素
*/
String driver="com.mysql.jdbc.Driver";
String url="jdbc:mysql://localhost:3306/spring";
String username="root";
String password="666888";

/**
* 创建jdbc需要的api
*/
Connection connection=null;
PreparedStatement pst=null;
ResultSet rs=null;


/**
* 通过反射创建需要映射的实体类
*/

Object student=null;
try {
student=Class.forName("cn.pb.bean.Student").newInstance();
} catch (Exception e) {
e.printStackTrace();
}


try {
//01.加载驱动
Class.forName(driver);
//02.获取连接
connection=DriverManager.getConnection(url,username,password);
//03.书写sql语句
String sql="select sid,age,sname from student where sid=?";
//04.给参数赋值
pst=connection.prepareStatement(sql);
pst.setInt(1,3);
//05.返回结果
rs=pst.executeQuery();

while (rs.next()){
//获取元数据的结果集 元数据:描述数据的数据
ResultSetMetaData metaData = rs.getMetaData();
System.out.println("元数据"+metaData);
int columnCount = metaData.getColumnCount();
//遍历元数据集合
for (int i=1;i<=columnCount;i++){
//获取数据库字段的名称
String columnName = metaData.getColumnName(i);
//获取数据库字段的类型 返回的类型都是大写
String columnTypeName = metaData.getColumnTypeName(i);

/**
* 01.给我一个元数据的名称
* 02.我去实体类中找对应的setXxx()
*/
String method = getMethod(columnName);
//赋值的时候根据类型
if(columnTypeName.equals("INT")){
student.getClass().getMethod(method,int.class).invoke(student,rs.getInt(columnName));
}else if(columnTypeName.equals("VARCHAR")){
student.getClass().getMethod(method,String.class).invoke(student,rs.getString(columnName));
}

 

}

Student stu= (Student) student;
System.out.println(stu);
}

} catch (Exception e) {
e.printStackTrace();
}finally {
try {
rs.close();
pst.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}

}


/**
* 01.用户给我一个字段名称(数据库中)
* 02.我们返回一个set+字段名 (首字母大写)
* @param name 字段名称
* @return 返回的set方法名称
*/
public static String getMethod(String name){//传过来sid 返回 setSid

return "set"+name.substring(0,1).toUpperCase()+name.substring(1);
}

 

8.编写九九666乘法表源码?

public class NineNine {
public static void main(String[] args) {
for (int i=1;i<=9;i++){
for (int j=1;j<=i;j++){
System.out.print(j+"*"+i+"="+(i*j)+"\t");
}
System.out.println();
}
}
}

 

9.列出你常见的设计模式?

01.工厂模式
02.单例模式
03.反射

 


10.手写出单例模式的两种实现方式?

01.单例模式: 保证整个系统中一个类 只有一个实例!而且这个实例只能是自身创建!外部不能直接创建对象! 不能new ! 只能通过类中的固定方法获取!
02.懒汉式
package cn.pb.singleton;

/**
* 懒汉式
*
* @author Administrator
* @2017年10月26日
*/
public class Singleton01 {
// 01.属性私有化
private static Singleton01 singleton01 = null;
private String name;
private int age;

// 02.私有化构造
private Singleton01() {

}

// 03.提供外部访问的接口 返回当前类的对象
public static synchronized Singleton01 getInstance() {
if (singleton01 == null) {
singleton01 = new Singleton01();

}
return singleton01;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

}
03.饿汉式
package cn.pb.singleton;

/**
* 饿汉式
*
* @author Administrator
* @2017年10月26日
*/
public class Singleton02 {
// 01.创建一个自己的实例 仅供自身访问
private static Singleton02 singleton02 = new Singleton02();
private String name;
private int age;

// 02.私有化构造
private Singleton02() {

}

// 03.提供外部访问的接口 返回当前类的对象
public static synchronized Singleton02 getInstance() {

return singleton02;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

}
04.双重锁
package cn.pb.singleton;

/**
* 双重锁
*
* @author Administrator
* @2017年10月26日
*/
public class Singleton03 {
// 01.创建一个自己的实例 仅供自身访问
private static Singleton03 singleton03 = null;
private String name;
private int age;

// 02.私有化构造
private Singleton03() {

}

// 03.提供外部访问的接口 返回当前类的对象
public static synchronized Singleton03 getInstance() {
if (singleton03==null) {
synchronized (Singleton03.class) {//再次加锁
if (singleton03==null) {
singleton03=new Singleton03();
}
}
}
return singleton03;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

}

 

posted @ 2017-10-31 21:59  迷茫王子  阅读(221)  评论(0编辑  收藏  举报