面试2——java基础2

11、MVC设计模型

mvc设计模型是一种使用model-view-controller(模型-视图-控制器)设计创建web应用程序的模式。是一种开发模式,好处是可以将界面和业务逻辑分离。

model:是程序的主体,主要包含业务数据和业务逻辑。是应用程序中处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。

view:视图层,就是UI界面,用于跟用户进行交互。一般所有的JSP、Html等页面就是View层。是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的

controller:是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据


12.什么是反射

在运行状态中,对于任意一个类,都能知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意方法和属性。

class Test{
    public void f(){
        System.out.println("base");
    }
}
class Sub extends Test{
    public void f(){
        System.out.println("sub");
    }
}
public class Test2{
    public static void main(String[] args) {
        try {
        //其中一种获得类的方法。 Class c
= Class.forName("Sub"); Sub v = (Sub) c.newInstance(); v.f(); }catch (Exception e){ e.printStackTrace(); } } }

 反射能做什么?

在运行时判断任意一个对象所属的类

在运行时构造任意一个类的对象

在运行时判断任意一个类所具有的成员变量和方法。

在运行时调用任意一个对象的方法

生成动态代理

反射机制获取类的三种方法:

//第一种方式:  
        Classc1 = Class.forName("Employee");  
        //第二种方式:  
        //java中每个类型都有class 属性.  
        Classc2 = Employee.class;  
   
        //第三种方式:  
        //java语言中任何一个java对象都有getClass 方法  
        Employeee = new Employee();  
        Class c3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee)
// 创建对象:获取类以后我们来创建它的对象,利用newInstance

        Class c =Class.forName("Employee");  
  
        //创建此Class 对象所表示的类的一个新实例  
        Object o = c.newInstance(); //调用了Employee的无参数构造方法.  

 13.java中的内部类和外部类

外部类:包含内部类的类称为外部类,外部类的修饰符只能是public,abstract,final。

内部类:内部类主要包括静态内部类,成员内部类,局部内部类和匿名内部类。内部类可以是静态static的,也可用public,default,protected和private修饰

静态内部类就是被声明为static的内部类,它可以不依赖于外部类实例而被实例化,静态内部类不能与外部类具有相同的名称,不能访问外部类的普通成员变量,只能访问外部类中的静态成员和静态方法。 

public class Test1 {
    static  double a = 1.333d;
    int b;
    static  class  Test{//  静态内部类
        public static void  main(String args[]){
            System.out.println(a);
            System.out.println(b); //访问外部非静态成员变量报错
        }
    }
}

成员内部类:即普通内部类,静态内部类去掉static关键字就是成员内部类,它可以自由的访问外部类的所有成员变量和方法(静态,非静态都可),只有外部类被实例化之后,这个类才能被实例化,需要注意的一点就是:非静态内部类中,不能有静态成员变量和静态方法

public class Test1 {
    static  double a = 1.333d;
    int b = 3;
    public  class Test2{//成员内部类
//        static  int aa;//成员内部类不能声明静态成员变量和静态方法。
       public  void  sum(){
           System.out.println(a+b);
       }
    }
    public static void main(String[] args) {
        Test1 test1 = new Test1();
        test1.new Test2().sum();  //外部类调用成员内部类中的方法。
    }
}

局部内部类:指定义在一个方法代码块中的类,作用范围仅是所在的代码块,是内部类中最少使用的一种类型。局部内部类像局部变量一样,不能被public,protected,private以及static修饰,只能访问方法中定义为final类型的局部变量

public class Test1 {
    static  double a = 1.333d;
    int b = 3;
    private  String out = "this in outer";
    
    public static void main(String[] args) {
        Test1 test1 = new Test1();
       // test1.new Test2().sum();  //外部类调用成员内部类中的方法。
        //test1.Test3();
        test1.Test3();
    }

    public void Test3(){
        final int c = 12;
        final double d = 33.333d;
        class innerclass{
            private  String out = "this is inner";
            public void method(){
                System.out.println(d+c);//内部类访问外部方法的变量,需要有final进行修饰。
                System.out.println(a);
                System.out.println(out);//局部内部类可以直接访问外部类的变量,即使是私有的
                System.out.println(Test1.this.out);//访问外部类中相同名称的变量
            }
        }
        innerclass innerclass = new innerclass();//在代码块中对局部内部类进行实例化。
        innerclass.method();
    }
}

匿名内部类:是一种没有类名的内部类,不使用关键字class,extends,implements,没有构造函数,他必须继承其他类或者其他接口,

  • 匿名内部类不能有构造函数
  • 匿名内部类不能定义静态成员/方法和类
  • 匿名内部类不能是public,protected,privated,static
  • 只能创建匿名内部类的一个实例
  • 一个匿名内部类一定是在new的后面,这个匿名类必须继承一个父类或实现一个接口
  • 因匿名内部类属局部内部类,所有局部内部类的所有限制都对其生效。
public class OuterClass {
            public InnerClass getInnerClass(final int   num,String str2){
                return new InnerClass(){
                    int number = num + 3;
                    public int getNumber(){
                        return number;
                    }
                };        /* 注意:分号不能省 */
            }
            public static void main(String[] args) {
                OuterClass out = new OuterClass();
                InnerClass inner = out.getInnerClass(2, "chenssy");
                System.out.println(inner.getNumber());
            }
        }
        interface InnerClass {
            int getNumber();
        }    

 14. 解释内存中的栈(stack)、堆(heap)和静态区(static area)的用法

定义一个基本的数据类型,一个对象的引用,函数调用的现场保存都使用内存中的栈空间;而通过关键字new和构造器创建的对象放在堆里;程序中的字变量(literal)如直接书写的100,hello和常量都是放在静态区中。

String str = new String("hello")  str存放在栈上,用new创建出来的字符串对象放在堆上,而“hello”这个字面量放在静态区


15. 获取数组的长度的方法为数组名.length;获取字符串的长度为length();二者不能混淆。


16. String、StringBuffer和StringBulider的区别?

它们都是final类,都不允许继承

public final class String
extends Object
implements Serializable, Comparable<String>, CharSequence


public final class StringBuffer
extends Object
implements Serializable, CharSequence


public final class StringBuilder
extends Object
implements Serializable, CharSequence

String长度不可以变,StringBuffer、StringBuilder长度可变

String长度不可变的原理(

 private final char value[];
//用final修饰的对象值可变,但是引用不变,即:value指向不可变,但是value[]数组的值可变,但因为有private关键字对其进行封装达到value[]数组值也不可变的目的

),StringBuffer和StringBulider是长度可变的。

StringBuffer是线程安全的,

StringBuilder不是线程安全的,StringBuffer在StringBuilder的方法之上添加了synchronized修饰,保证线程安全。

StringBuilder拥有更好的性能

如果一个String类型的字符串,在编译时就可以确定一个字符串常量。此时,String的性能比StringBuilder更好


17. Java内存分配位置

a:基础数据类型直接在栈空间分配。

b:方法的形式参数,直接在栈空间分配,当方法调用完成后从栈空间回收。

c:引用数据类型,需要new来创建的,现在栈空间分配一个地址空间,实际的类变量的值放在堆空间中。

d:方法的引用参数,在栈空间分配一个地址空间,并指向堆空间的对象区,当方法调用完后从栈空间回收。

e:局部变量new出来时,在栈空间和堆空间中都分配空间,当局部变量生命周期结束后,栈空间立即被回收,堆空间区域等待GC回收。

f:方法调用时传入的实际参数,先在栈空间分配,在方法调用完成后从栈空间释放。

g:字符串常量在DATA区域分配,this在堆空间分配。

h:创建的数组在栈空间分配数组名称,在堆空间分配数组实际的大小。

 类中的成员变量,存放在堆区;方法中的局部变量,存放在栈区


 18:static关键字的用法:

“static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。”————《Java编程思想》

1) static方法

用static进行修饰方法的方法一般称为静态方法,静态方法不依赖任何对象就可以进行访问。在静态方法中不可以访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。但是要注意的是在非静态成员方法中是可以访问静态成员方法/变量的。

public class T1 {
    static int aaa = 111;
    int b = 19;
    public static void name1() {
        System.out.println("这是一个静态方法");
        System.out.println(aaa);
        //System.out.println(b);//报错,不能访问非静态变量
    }
    public void name() {
        System.out.println("这不是一个静态方法");
        System.out.println(b);
        System.out.println(aaa);
        //T1.name1();
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //T1.name1();//直接可以通过类名.方法名访问
        //int a =  10;
        T1 t1 = new T1();
        //t1.name(a);
        t1.name();//访问非静态方法必须通过实例化对象,进行访问。
    }
}

2)static变量

static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。static成员变量的初始化顺序按照定义的顺序进行初始化。

3)static代码块

static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。


19.Java执行顺序

public class Parent {
    static int t = parentstaticmethod();//父类静态成员变量
    {
        System.out.println("父类非静态方法代码块");
    }
    static{
        System.out.println("父类静态方法代码块");
    }
    public Parent(){
        System.out.println("父类构造方法");
    }
    public static int parentstaticmethod(){
        System.out.println("父类静态方法");
        return 19;
    }
    public static void main(String[] args) {
        Child child = new Child();
    }
}
 class Child extends Parent{
     {
            System.out.println("子类非静态方法代码块");
        }
        static{
            System.out.println("子类静态方法代码块");
        }
        public Child(){
            System.out.println("子类构造方法");
        }
        public static int childstaticmethod(){
            System.out.println("子类静态方法");
            return 19;
        }    
}

结果

父类静态方法
父类静态方法代码块
子类静态方法代码块
父类非静态方法代码块
父类构造方法
子类非静态方法代码块
子类构造方法
View Code

20.序列化和反序列化

当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。

在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存。比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些seesion先序列化到硬盘中,等要用了,再把保存在硬盘中的对象还原到内存中。

序列化:把java对象转换为字节序列的过程

反序列化:把字节序列恢复为java对象的过程

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.MessageFormat;

public class TestObjSerializeAndDeserialize {
    static String pathname =  "d:/Person.txt";
    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
         SerializePerson();
         Person person =deSerializePerson();
         String pattern ="name={0},age={1},sex={2}";
         Object[] arguments = {person.getName(),person.getAge(),person.getSex()};
         System.out.println(MessageFormat.format(pattern, arguments));
         
    }
    private static void SerializePerson() throws FileNotFoundException,IOException{
        Person person = new Person();
        person.setAge(25);
        person.setName("nana");
        person.setSex("女");
        ObjectOutputStream oo =  new ObjectOutputStream
                (new FileOutputStream(new File(pathname)));
        oo.writeObject(person);
        System.out.println("对象序列化成功!");
        oo.close();    
    }
    public static  Person deSerializePerson() throws Exception,IOException{
        ObjectInputStream oiStream = new ObjectInputStream
                (new FileInputStream(new File(pathname)));
        Person person = (Person) oiStream.readObject();
        System.out.println("反序列号成功");
        return person;
    }
}
原文地址:https://www.cnblogs.com/znn93/p/9203553.html