1、基本数据类型跟封装类型

  • 整型:byte、int、short、long
  • 浮点型:float、double
  • 字符型:char
  • 布尔型:boolean
  • 在sh中写java_封装


在sh中写java_封装_02

1、基本类型与封装类型数据之间的转换valueOf()

public class StringtoNum { //主类名需要和文件名一致
 //这是个main 函数
public static void main(String[] args)
//从数据库里取到的num 是String 类型
String num =”123”;
//通过Integer 封装类进行数据转换
int intVal = Integer.valueOf(num);
//通过Float 封装类进行数据转换
float fltVal = Float.valueOf(num);
//通过Long 封装类进行数据转换
long longVal = Long.valueOf(num);
//依次输出三个转换后的变量
System.out.println(intVal);
System.out.println(fltVal);
System.out.println(longVal);

2、i++与++i的使用建议

  • i++是指表达式运算完后i再加1
  • ++i是指i加上1后再运算表达式的值

为了提升代码的可读性,建议左加加和右加加操作不应(或尽量少)和他操作符混用,如果实在有必要,要分开写。

int i = 10;
int j = 10;
int k;
//k = i++ *3  不建议!!!++i也是一样
k = i * 3 ;
i ++;

3、三目运算代替if语句

表达式1 ?表达式2 : 表达式3;

语法:判断表达式1的返回值,如果是true 则执行表达式2 ,否则执行表达式3 。

int x = 1001;
String yhx = "nice";
if(x > 1000)
    yhx = "good";
else
    yhx = "nice";
//三目运算
x > 1000 ? yhx = "good": yhx = "nice";

4、==与equals的区别

  • 对于基本类型,== 比较值是否相等;对于封装类型,== 比较在内存中存在的地址是否相等。
  • 对于封装类型,equals 比较它们的值是否相等;
public class BasicGrammer {
    public static void main(String[] args) {
        boolean flags = true;
        int i = 10;
        int j = 10;
        flags = (i == j) ? true : false;
        System.out.println(flags);  //true
        Integer x = new Integer("10");
        Integer y = new Integer("10");
        System.out.println(x.equals(y));  //true
        System.out.println(x == y);       //false
    }
}

5、常用面试题

( 1 )简述&和&&,以及|和||的区别。

答:& 和 |是位运算符,不常用;&& 和||是逻辑运算符,通常在if、while、for中使用。

( 2 )运行short s1 = 1, s1 = s1 + 1 ;会出现什么结果?运行short s1 = 1; s1 += 1 ;又会出现什么结果?

答:运行第一个会报错,因为1是int类型,而s是short类型,通过+运算后s1自动转换成int型。错误提示:Error:(21, 17) java: 不兼容的类型: 从int转换到short可能会有损失
运行第二个是正确的,s1=2,+1是int类型的操作,s1自动转换int类型

( 3 )用最高效率的方法算出2 乘以8 等于多少。

移位运算符:int i = 2 << 3;

( 4 ) “ == ”和equals 万法有什么区别

==在基本类型,比较值是否相等,在封装类型中比较内存中的地址
equals在封装类型中比较值是否相等,

( 5 )Integerint的区别是什么。

Integer是封装类型,包含int基本类型的基本操作,int是基本类型

12 , -12

( 7 )floatfloat f = 3.4是否正确?

No!!精度不正确,float f = 3.4f或者float f = (float)3.4

2、流程控制

1、if …else

以闰年为例

public class BasicGrammer {
    public static void main(String[] args) {
       int year = 2020;
       if((year % 4 ==0 && year % 100 != 0) || (year % 400 == 0)){
           System.out.println("yes");
       }else {
           System.out.println("no");
       }
    }
}

注:在表达式不要多次使用逻辑表达式&&和||,如果需求很复杂,应分解多个if…else语句

2、避免短路效应

这里主要讲&&跟||在if语句中使用!

  • if(表达式1 && 表达式2)若表达式1为false,那么不管表达式2是true or false,都不会执行表达式2,if语句为false,就没有意义了
  • if(表达式1 || 表达式2)若表达式1为true,那么不管表达式2是true or false,都不会执行表达式2,if语句为true
public class BasicGrammer {
    public static void main(String[] args) {
    int a = 2 ;
    int b = 3 ;
    if(a > 0 || b-- > a ){
        System.out.println(b);   //b = 3
    }if (a < 0 && ++b > 0){
        }else {
            System.out.println(b);  // b = 3
        }
    }
}

3、swtich中的default和break

public class BasicGrammer {
    public static void main(String[] args) {
        char grade = 'A';
        switch (grade){
            case 'A':{
                System.out.println("1000");
                break;
            }
            case 'B':{
                System.out.println("8000");
                break;
            }
            case 'C':{
                System.out.println("600");
                break;
            }
            case 'D':{
                System.out.println("400");
                break;
            }
            case 'E':{
                System.out.println("200");
                break;
            } default:{
                System.out.println("nice");
            }
        }
    }
}

**对于每个case语句,都要加上break,若没有break,则输出就变了,没加break的case都会输出!!**如果不加break ,即使执行完本部台case 分支后,还会执行后继的分支语句。

不加default不会报错,但强烈加上!!!

4、常用面试题

( 1 ) switch 语句能否作用在byte 、long 、String 上?

  • 可以用在byte、int、short、char以及它们的封装类上
  • 不能用在其他基本类型上long、double、float、boolean以及封装类
  • jdk1.7及以上,可以用以字符串
  • 可以用于枚举类型

( 2 )在Java 中,如何跳出当前的多重嵌套循环。

break or continue ; break跳出整个循环;continue跳出当前循环。

( 3 ) while 和do while 有什么区别?

  • while是先判断再执行;do…while是先执行再判断,同等条件下,后者多执行了一次。

( 4 )你有没有用过关键字goto ?并简述你的看法。

不建议使用!会破坏程序的结构,可读性变差

3、String对象

String 对象虽然简单,但会召出“内存内容不可变”

1、String定义变量和常量

String str = "abc";               //定义一个常量,存放在常量池中
String str =new String ("abc");  //定义了一个变量,存放在堆空间
  • String 常量存放在常量油中, Java 虚拟机出于优化的考虑1 会让内容一致的对象共享内存块,但变量是放在堆空间中的, new意义的不同变量内存地址不会相同。
  • String 常量连接常量,还是常量,依然用常量池管理,但变量连接常量就是变量了。

2、String 来了解“内存值不可变”

......main方法省略
	String a =” 123456789 ”;
    System.out.println(a.substring(0,5)) ;//12345
    String b = "123456789 ”;             //假设1000 号内存放123456789
    b.substring(0,5);                   //开辟了2000 号内存,存放12345,但没返回,b值没变
    //b = b.substring(0,5);              // 开辟3000 号内存,存放12345
    System.out.println(b);               //1000 号内存依然是123456789
  • 尽可能使用常量,如String a ="123 ”避免使用变量,如String a = new String("123 ”)
  • 尽量避免大规模地针对String 的(如连接字符串)操作,因为这样会频繁地主成内存碎片,导致内存性能问题。如果遇到这种业务需求,应改用后面提到的StringBuilder对象。
  • 如果确实有需求,应采用c = c.replace ('1','2'), 的写法,而不是直接写成c .replace( '1','2')

3、String 和String Builder 的区别查看内存优化

频繁对字符串进行操作,应使用StringBuilder,它是可变的,不会像String产生内存碎片

public class StringBuilderdemo {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();  //创建一个对象
        sb.append("yhx love ").append("lwh");    
        //sb = sb.append("yhx love ").append("lwh");是错误的 
        System.out.println(sb.substring(3,8));    //love
        //String val = sb.substring(3,8);而不是StringBuilder接收对象 
        System.out.println(sb);                  //yhx love lwh
        sb.replace(3,8," very like");             //替换
        System.out.println(sb);                    //yhx very like lwh
        sb.deleteCharAt(0);
        System.out.println(sb);                    //hx very like lwh
    }
}

总结:

  • StringBuilder线程不安全,StringBuffer线程安全
  • 为了保持线程安全的特性,StringBuffer性能略低于StringBuilder
  • 单线程情况下,使用StringBuilder

4、会被不知不觉调用的toString方法

public class toString {
    public static void main(String[] args) {
        int val = 1001;
        System.out.println(val);
        float floatValue = 10;
        System.out.println(floatValue);
        char c = 'a';
        System.out.println(c);
        Integer integer = new Integer("1001");
        System.out.println(integer.toString());
        StringBuilder builder = new StringBuilder();
        builder.append("1001");
        System.out.println(builder);
        System.out.println(builder.toString());
    }
}
  • System.out.println()方法能根据不同类型的输入参数(如intfloatlnteger等)适当地完成输出
    动作,称为多态。
  • 当自己定义类时,如果要让这个类输出合适值,需要在冥中自己定义toStirng方法。

5、String对象需注意

  • String a =” 123”通过这种方式定义的是常量,String a =new String("123");,通过这种方式定义的是变量。
  • == 是比较地址值是否一致,而**equals 是比较内容**是否一致。
  • String常量(不仅是String,Integer等常量也是)是放在常量池中的,值相同的常量是共享同一块内存的,通过==比较它们的内存地址值是相同的。
  • 通过String定义出来的值在内存中是不可变的,如果频繁地操作String,会产生内存碎片,不幸IJ于内存性能管理,遇到这种情况,建议使用String BuilderString Buffer,如果在单线程情况下,出于性能因素的考虑,建议使用String Builder
  • 在通过System.out. println 输出时,默认I也会调用toString方法,如果自己定义类,可以通过toString来定义类的输出结果。

6、常见面试题

( 1 ) String咱是最基本的数据类型吗?能不能被继承。

不能被继承,它只是一个对象

( 2 ) String s =new String("xyz");,创建了几个String 对象?二者之间再什么区别。

2个对象,一个是内存中的xyz,一个是s,指向xyz

( 3)StringString Buffer的区别是什么?

  • String频繁操作字符串,会产生内存碎片,不可变
  • String Buffer不会产生内存碎片,可变

( 4) String BufferString Builder的区别是什么?

  • StringBuilder线程不安全,StringBuffer线程安全
  • 为了保持线程安全的特性,StringBuffer性能略低于StringBuilder
  • 单线程情况下,使用StringBuilder

( 5) String 类是不可变类, 以String为例简述什么是不可变类。

( 6) String a = "12345"; a.substring(0,2);此时a 的值是什么?

a = “12345”,因为没有返回

( 7) String a = "1 " ; String b = " 1 ”,那么a==b的值是true还是false?并说明理由。

true ,因为a,b都是常量

4、封装:类和方法

1、类和实例的区别

class关键字定义类,new 关键字创建一个对象(实例)

2、合理的访问控制符实现封装

  • 如果没有特殊的需求, 把类内部的属性变量设置成私有的,通过公有的get 和set 万法来让外部使用。也有不少人为了省事,会设置成public ,如果积累多了会烦琐。
  • 如果有特殊需求,把类的构造函数设置成公有的,否则在外部没法使用。
  • 尽可能地在类、方法和属性变量前添加访问控制符。

访问控制符

同类

同包

子类

不同包

public

能访问

能访问

能访问

能访问

protected

能访问

能访问

能访问

不能访问

default

能访问

能访问

不能访问

不能访问

private

能访问

不能访问

不能访问

不能访问

3、静态方法和静态变量

静态类中只能使用静态方法和静态变量

public class Static { private static int value = 1001; static void setStatic(){ System.out.println(Math.abs(value)); } public static void main(String[] args) { Static.setStatic(); } }

  • 由于可以不用new 就能使用万法, 一些程序员为了省事,会大量定义静态方法;这样会破坏类的封装性,而
    且会增加类之间的耦合度,因此只能在需要时定义静态类。
  • 静态变量相当于全局变量,所以只把整个项目中都会用到的变量设置成静态的。
  • 在尽可能小的范围中使用静态类和静态方法。

5、继承:类的继承和接口的实现

从语法角度来看,可以通过extends 来继承父类, 可以通过implements 来实现接口。
从项目角度来看, 一般把通用的代码放入父类和接口中,这样可以避免大面积地重复代码。

接口和抽象类有什么区别?

从设计层面来说,抽象是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范。

1、子类覆盖父类的方法

class person(){
    protected void speck(){}
}
class ChinesePerson extends person(){
     protected void speck(){}
}

( 1) 子类方法不能缩小父类方法的访问权限,如在上述第5 行覆盖父类的方法时,修饰符可以是protected ,也可以是更大的public ,但不能是缩小的private 。在父类中定义的private 方法,子类不能看到,所以也不存在缩小访问权限的问题,如果在父类中定义protected 、public 或默认的方法,总是希望子类能用到或重写,但如果缩小范围,如把第5 行的protected 缩小成private ,那么ChinsePerson 的子类就看不到爷爷类(也就是Person类)的speak 方法就会造成“父类方法失传”的问题。
( 2 )子类方法不能抛出比父类方法更多的异常,关于原因等,我们在后面讲到异常处理时再作分析。

2、不能回避的final关键字

final 关键字相继承、方法的覆盖高直接的关系。它能作用到类、方法和属性上。

  • final作用在类上,此类不能被继承
final class Student{
    String id;
    public String get Id () {return id;}
    public void setid(String id) { this . id = id;}

 class subStudent extends Student {}//这句话会出错
  • final作用在方法上,此方法不能被重写(不能被子类覆盖)
class Student{
final void print() {}
}
  • final作用在属性上,此属性相当于常量,如赋予初始值,该值不能改变
final Stirng a = "1";
String b = "1";
String c = "123";
String d = b + "23"; //此时d是一个变量,不等同于String d = "1" + "23";这个d是常量
System.out.println(c==d);  //false
String e = a + "23"; //e是一个常量,因为final修饰a,a是一个常量
System.out.println(c==e);  //true
//a = "4"; ✖

3、理解finalize 方法,但别重写

Java 虚拟机提供了专门的垃坡回收机制,所高用不到的类都会由Java 虚拟机来回收?这个回收动作对程序员来说是透明的。
当虚拟机回收类时,会自动地调用该类的finalize 万法,如果类中没定义,会词用Object 类中的finalize , 而Object 中的finalize 万法是空白的。

  • 要了解finalize 方法有什么用,它什么时候会被调用;
  • 大家在自定义的类中不要重写finalize 方法,如果写错,就会导致类无法被回收,从而导致
    内存使用量直线上升最后抛出内存溢出的错误。

6、多态:同一方法根据不同的输入有不同的作用

1、方法重载实现多态

class demo{
    public void print();
    public void print(int row){
        System.out.println("with 1 int param");
    }
    public void print(int row,int column){
        System.out.println("with 2 int param");
    }
    public void print(int row,String type){
        System.out.println("with 1 int param,with 1 String param");
    }
    ...
}

注:

  1. 判断重载时,Java编译器只看参数类型,不看参数名
public void print(int row)
public void print(int column)
  1. 修改方法的返回值实现重载
public void print(int row,int column)
public String print(int row,int column)

2、方法的重载和覆盖

方法的重载( Overload )和覆盖( Override )是面试时常考的点

class Base{
 public void print () { )
 //是重载,因为参数不同
 public void print (int row) {)
 //是重载,因为参数类型不同
 public void print(String type){}
 class Child extends Base{
 //是覆盖,覆盖了父类的同名无参方法
 public void print() {}
 //出锚, 因为父类已经有带int 参的同名方法
 public String print(int row){}
 //是覆盖, 覆盖了父类的带String 参的同名方法
 public void print(String type){}
     //是重载,因为参数个数不同
 public void print(int row, String type ) {}
 }

 publiC class DifferenceDemo {
 public static void main (String [] args) {
 }
  • 如果方法名、参数和返回类型都一致,那么可以说是子类的方法覆盖了父类的方法。
  • 如果方法同名、参数个数或类型不同,这时无须看返回类型,这种情况属于重载。
  • 当把子类中的方法移动到父类后,两个同名方法参数完全一致,但返回类型不同,这种属于语法错误, Java
    编译器会报“定义了重复方法”的锚误。

3、构造函数能重载但不能覆盖,兼说this 和super

构造函数是一种特殊的、不带返回值的方法,它在创建类(如new )时被调用。

错误示范:

class parent{
    private int val;
    public parent(int val){this.val = val}
}
class Subclass extends parent{
    public Subclass(int i){  //系统默认添加super()调用父类无参构造,而父类中没有无参构造
        //super(i);        法2:父类中加入无参构造
    }  
}

经常用到的写法:

class Parent{
    private int value ;
    private String msg ;
    //在不带参的构造函数中通过this 调用带两个参的构造函数
    public Parent(){ this(O ,” call with No Param Function ”);}
    public Parent (int val )
    {this . value =val ;  //通过this 给本类的value 赋值
     System.out.println ( ” with one param ”);
    }
    public Parent (int val , String msg){
        System.out.println (”msg is :”+ msg) ;
        System.out.println (” with 2 param”);
    }
}
class Subclass extends Parent{
    public Subclass (int i) {//通过super ,调用父类的带一个参的构造函数
        super(i);
        System.out.println (” in subclass ”);
    }
}
public class ConstructDemo {
    public static void main(String[] args) {
        Parent pO =new Parent();    //msg is:call with No Param Function + with 2 param
        Parent pl =new SubClass(l); // with one param + in subclass
        Parent p2 =new Parent(l ,”new Parent”); //msg is new Parent + with 2 param
        //Subclass s =new Parent(l); //error
    }
}

项目中在有继承的情况下重载构造函数的常规用法:

  • 在一个类中可以定义多个构造函数,在构造函数中,经常能看到this. value = xx的写法, 这是根据输入的参数给本对象的属性赋值, 也能经常看到this(xx , " xxx ")的做法,这是在一个构造函数中调用真他的问造函数。
  • 在子类的构造函数体中,如果什么代码都不写, Java 编译器会默认加上super(),以调用父类中的不带参的构造 函数,如果父类中没有不带参的问造函数,会提示语法错误。要解决这个语法错误,可以在父类中定义一个带参的构造函数,或者加上super语句。

this 指向所在方法的本类

  • 场景一:this.value = xxx,根据输入的参数给本对象复制
  • 场景二:this(O ,xxx ),调用本类的带有两个参数的构造方法

super 是指向所在方法的父类,如这里是用super(xx)来调用父类的构造函数

4、通过多态减少代码修改成本

多态要解决的问题是:把抽象的业务逻辑和具体的实施细节分离,通俗地讲,多态可以分为“做什么”和“怎么做”。

多态有“修改点隔富”和“无障碍扩展”两大好处。

  • “修改点隔离”是指当用户修改了业务方法的内部实现细节后,调用者可以在毫不知情的情况下继续使用,
  • “无障碍扩展”是指如果遇到添加新功能的需求时,可以在不大量修改现有代码的前提下完成添加工作。

继承+覆盖

abstract class Employee
{ protected abstract void talkBusiness() ;
 //Sales 继承Employee
 class Sales extends Employee {
     public void talkBusiness()
     {System.out.println(” Sales talk business. ”);}
 }
 //Manager 继承Employee
 class Manager extends Employee{
     public void talkBusiness ()
     {System.out.println (”Manager talk business.”);}
 }
 public class ExpandDemo {
     public static void main(String[) args){
         Employee sales =new Sales();
         sales.talkBusiness();  //Sales talk business
         Employee manager =new Manager();
         manager.talkBusiness(); //Manager talk business.
     }
}
  • 如果要修改业务员和客户交流的业务代码,只需修改Sa l e 类的方法,无须更改其他的类和方法。
  • 如果公司要增加新的业务,如要加上“总经理和客户交流”的业务动作,只需新增一个总经理类,让它继承Employee 类,然后在其中定义talkBusiness 方法即可。

5、面向对象思想的常用面试题

1、开放性问题,简述你对面向对象思想的了解?

要点1 :先说基础概念,如面向对象思想包括封装、继承、多态,再说些语法,如可以通过Extends 继承类、通过Implement 来实现接口。
要点2 :要结合具体实际简述在你做过的项目中1面向对象思想带来的具体好处,如结合一个具体的例子(如电信系统),介绍一下把方法都定义到父类中,然后通过继承子类来扩展,能改善代码结构,通过多~某减少代码修改后的维护量。注意不能只说理论,要结合你项目中的例子。

2、接口和抽象类有什么区别?

从设计层面来说,抽象是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范。

3、重载( Overload )和覆盖( Override )的区别是什么?

区别重载重写(覆盖)参数列表必须修改一定不能修改返回类型可以修改一定不能修改异常可以修改可以减少或删除,一定不能抛出新的或者更广的异常访问可以修改一定不能做更严格的限制(可以降低限制)

方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。

  • (1)方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。
  • (2)方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。
  • (3)方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。

4、this 和super的含义

this 指向所在方法的本类

  • 场景一:this.value = xxx,根据输入的参数给本对象复制
  • 场景二:this(O ,xxx ),调用本类的带有两个参数的构造方法

super 是指向所在方法的父类,如这里是用super(xx)来调用父类的构造函数

5、finalize方法有什么作用。

  • finalize 方法在类被回收时被调用;
  • 一般在项目中不会重写这个万法,因为可能会引发内存无法回收的问题

6、final 关键的含义。

  • final作用在类上,此类不能被继承
  • 作用在方法上,不能被重写(不能被子类覆盖)
  • 作用在属性上,相当于常量,如赋予初始值,则该值不能被改变

7、构造函数能否被覆盖,能否被重载?

可以重载,不能覆盖

8、静态变量和实例变量的区别有哪些?

  • 静态变量存储在方法区,属于类所有.实例变量存储在堆当中,其引用存在当前线程栈.
  • 语法上:静态变量加static,实例变量不加
  • 静态变量不需要创建实例对象就可以直接使用类名进行引用;实例变量只有在创建了实例对象之后才会被分配空间,才可以使用
  • 静态变量属于类,该类不生产对象,通过类名就可以调用静态变量;实例变量属于该类的对象,必须产生该类对象,才能调用实例变量。

9、是否可以从一个static 方法内部发出对非static方法的调用。

不可以。static方法是静态方法,是属于类的方法,非static方法是属于对象的方法。因为非static方法是要与对象关联在一起的,必须在创建出一个对象后,才可以通过这个对象调用非static方法;而static方法可以直接通过类名来调用,不需要创建对象。也就是说,在一个static方法被调用时,还可能没有创建任何实例对象,此时如果从static内部发出对非static方法的调用,非static方法是无法关联到对象的。

static的意义在于方便在没有创建对象的情况下来进行调用(方法/变量)。

10、简述作用域public 、private 、protected 及不写时的区别。

访问控制符同类同包子类不同包public能访问能访问能访问能访问protected能访问能访问能访问不能访问default能访问能访问不能访问不能访问private能访问不能访问不能访问不能访问