那些年让我蹚浑水的java基础

1.String和StringBuffer的区别?

1.String类表示的字符串是常量,一旦创建后,内容和长度都是无法改变的。而StringBuffer表示字符容器,其内容和长度都可以随时修改。在操作字符串时,如果该字符串仅用于表示数据类型,则使用String类即可,但如果需要对字符串中的字符进行增删操作,则使用StringBuffer类。
2.String类覆盖了Object类的equals()方法,而stringBuffer类没有覆盖Object类的equals()方法。
3.String类对象可以用操作符+进行连接,而StringBuffer类对象之间不能。

2. “== ”和equals方法究竟有什么区别?

“== ”操作符专门用来比较两个变量的值是否相等,即比较变量对应的内存中所存储的数值是否相同,用于比较两个基本类型或两个引用变量的值是否相等。
如果一个变量指向的数据是对象类型的,那么,这时候涉及了两块内存,对象本身占用一块内存(堆内存),变量也占用一块内存,例如Object obj = new Object();引用变量obj占用一块内存,new Object()占用另一块内存,此时,变量obj所对应内存中存储的数值就是对象占用的那块内存的首地址。对于指向对象类型的引用变量,如果要比较两个变量是否指向同一个对象,即要看这两个引用变量所对应的内存中的数值是否相等,这时候就需要用“== ”操作符进行比较。
equals方法用于比较两个独立对象中的内容是否相同,它比较的两个对象是独立的。例如:String a = new String(“foo”); String b= new String(“foo”);两条new语句创建了两个对象,然后用a,b这两个引用变量分别指向其中一个对象,这是两个不同的对象,它们的首地址是不同的,即a和b中存储的数值是不同的,所以a== b将返回false,而这两个对象中的内容是相同的,所以表达式a.equals(b)将返回true。
实际开发中,经常要比较传递进来的字符串内容是否相等,比较字符串内容是否相等,一般使用equals方法。例如,String input = ….;Input.equals(“quit”); 而使用“== ”比较就是错误的。
如果一个类没有自己定义equals方法,那么它将继承Object类的equals方法,Object类的equals方法代码如下:
boolean equals(Object o){
return this == o;
}
这说明,如果一个类没有自己定义equals方法,它默认的equals方法(从Object类继承的)就是使用“== ”操作符,也是在比较两个变量指向的对象是否是同一对象,这时候使用equals和使用“==”会得到同样的结果,如果比较的是两个独立的对象则总返回false。如果你希望编写的类能够比较该类创建的两个实例对象的内容是否相同,那么你必须覆盖equals方法,由你自己写代码来决定在什么情况下即可认为两个对象的内容是相同的。

3. 方法重载(Overload)和方法重写(覆盖)(Override)有什么区别?

重载表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同),因为当我们调用重载的方法时,VM会根据不同的参数列表来选择合适的方法执行。访问权限,返回类型,抛出的异常(个数和类型)都不能实现重载。(也就是说方法的重载与返回值类型,方法访问权限,方法抛出的异常都无关)。
重写表示子类中的方法可以与父类中的某个方法名称和参数列表完全相同,通过子类创建的实例调用这个方法时,将调用子类中定义的方法,这相当于把父类中定义的完全相同方法给覆盖了,这也是面向对象编程的多态性的一种表现。子类覆盖父类方法时,返回值类型必须和父类方法返回值类型一致,只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常,因为子类可以解决父类的一些问题,不能比父类有更多的问题。子类方法的访问权限只能比父类的更大,不能更小。如果父类的方法是private的,那么,子类则不存在覆盖的限制,相当于子类中增加了一个全新的方法,所以被重写的父类方法不能为private。最熟悉的重写就是对接口方法的实现,在接口中一般只是对方法的声明,而我们在实现该接口时,需要实现接口声明的所有有方法;继承中也会存在子类重写父类中的方法,要求子类中重写的方法和父类被重写的方法具有相同的方法名、参数列表以及返回值类型。子类重写方法的访问权限应该比父类被重写方法更开放,但是抛出的异常数量要更少,类型更小(父类抛出异常类型的子类型)。

4. 面向对象的概念:

面向对象是一种符合人类思维习惯的编程思想。现实生活中存在各种形态不同的事物,这些事物之间存在着各种各样的联系。在程序中使用对象来映射现实中的事物,使用对象的关系来描述事物之间的联系,这种思想就是面向对象。

4. 面向对象的三大属性:封装性、继承性、多态性

面向对象的概念:现实生活中存在各种形态不同的事物,这些事物之间存在着各种各样的联系。在程序中使用对象来映射现实中的事物,使用对象的关系来描述事物之间的联系,这种思想就是面向对象。使用面向对象的思想解决问题时,把待解决的问题按照一定规则划分为多个独立的对象,然后通过调用对象的方法来解决问题。
封装性:面向对象的核心思想,将对象的属性和行为封装起来,不需要让外界知道具体实现细节,这就是封装思想。类的封装是指在定义一个类时,将类中的属性私有化(用private关键字修饰),私有属性只能在它所在类中被访问。为了能让外界访问私有属性,需要提供一些使用public修饰的公有的getter/setter方法。
继承性:主要描述类与类之间的关系,通过继承,可以在无须重新编写原有类的情况下,对原有类的功能进行扩展。继承增强了代码复用性,提高开发效率,为程序的修改补充提供了便利。类的继承是指在一个现有类的基础上去构建一个新的类,构建出来的新类被称作子类,现有类被称作父类,子类会自动拥有父类所有可继承的属性和方法。
多态性:在一个类中定义的属性和方法被其他类继承后,他们可以具有不同的数据类型或表现出不同的行为,这使得同一个属性和方法在不同的类中具有不同的语义。在设计一个方法时,通常希望该方法具备一定的通用性。例如要实现一个动物叫的方法,由于每种动物的叫声不同,因此可以在方法中接收一个动物类型的参数,当传入猫类对象时就发出猫类的叫声,传入犬类对象时就发出犬类的叫声。在同一个方法中,这种由于参数类型不同而导致执行效果不同的现象就是多态。在Java中为了实现多态,允许使用一个父类类型的变量来引用不同的子类类型的对象,根据被引用子类对象特征的不同,得到不同的运行结果。多态不仅解决了方法同名的问题,而且使程序变得更加灵活,从而有效提高程序的可扩展性和可维护性。

5. this关键字:

问题描述:
在一个类中,使用变量表示年龄时,构造方法中使用的是con_age,成员变量使用的是age,这样的程序可读性很差。此时,需要将一个类中表示年龄的变量进行统一的命名,例如都声明为age。但这样做又会导致成员变量和局部变量的名称冲突,在方法中将无法访问成员变量age。为解决这个问题,Java中提供了一个关键字this,用于在方法中访问对象的其他成员。
this的三种用法:

  1. 通过this关键字明确访问一个类的成员变量,解决与局部变量名称冲突问题
  2. 通过this关键字调用成员方法。
  3. 构造方法是在实例化对象时被Java虚拟机自动调用的,在程序中不能像调用其他方法一样去调用构造方法,但可以在一个构造方法中使用“this([参数1,参数2….])”的形式来调用其他的构造方法。在使用this调用类中其他构造方法时,要注意的3个坑:1.只能在构造方法中使用this调用其他的构造方法,不能再成员方法中进行。
    2.在构造方法中,使用this调用构造方法中的语句必须位于第一行,且只能出现一次。
    3.不能在一个类的两个构造方法中使用this互相调用,否则编译报错。

6.static关键字:

static关键字可以用于修饰类的成员,如成员变量、成员方法、代码块等,被static修饰的成员具备一些特殊性。
静态变量:在定义一个类时,只是在描述某类事物的特征和行为,并没有产生具体的数据。只有通过new关键字创建该类的实例对象后,系统才会为每个对象分配空间,存储各自的数据。有时候,我们希望某些特定的数据在内存中只有一份,而且能够被一个类的所有实例对象所共享。在一个Java类中可以使用static关键字来修饰成员变量,该变量被称作静态变量。静态变量被所有实例共享,可以使用“类名.变量名”的形式来访问。此处有坑:static关键字只能用于修饰成员变量,不能用于修饰局部变量,否则编译会报错。
静态方法:有时候我们希望在不创建对象的情况下就可以调用某个方法,也就是说这个方法不必和对象绑在一起。只需要在类中定义的方法前加上static关键字即可实现这种效果。
静态方法和静态变量一样,都可以使用“类名.方法名”的方式来访问,也可以通过类的实例对象来访问。此处也有坑:在一个静态方法中只能访问用static修饰的成员,原因在于没有被static修饰的成员需要先创建对象才能访问,而静态成员在被调用时可以不创建对象。
静态代码块:在Java类中,使用一对大括号包围起来的若干行代码被称为一个代码块,用static关键字修饰的代码块称为静态代码块。当类被加载的同时,静态代码块会执行,由于类只加载一次,因此静态代码块只执行一次(无论静态代码块所在类实例化多少次,只在第一次实例化时执行该静态代码块)。在程序中,通常会使用静态代码块来对类的成员变量进行初始化。

7. 内部类:

在Java中,允许在一个类的内部定义类,这样的类称作内部类,这个内部类所在的类称作外部类。根据内部类的位置、修饰符和定义的方式可分为成员内部类、静态内部类、方法内部类。

  1. 成员内部类:一个类中除了可以定义成员变量、成员方法,还可以定义类,这样的类被称作成员内部类。在成员内部类中可以访问外部类的所有成员。如果想通过外部类去访问内部类,则需要通过外部类对象去创建内部类对象,创建内部类对象的形式:
    外部类.内部类 变量名 = new 外部类名().new 内部类名();是不是感觉很奇怪?事实上的确是这样的。这里有坑:如果内部类被声明为私有(使用private修饰),则外界无法访问。
  2. 静态内部类
    使用static关键字修饰的成员内部类称作静态内部类,它可以在不创建外部类对象的情况下被实例化。在静态内部类中只能访问外部类的静态成员,否则编译报错。创建静态内部类对象的形式:
    外部类名 . 内部类名 变量名 = new 外部类名 . 内部类名();
    此处有坑:在静态内部类中可以定义静态成员,而在非静态的内部类中不允许定义静态的成员。
  3. 方法内部类
    在成员方法中定义的类称作 方法内部类,它只能在当前方法中被使用。(即程序只能在方法中创建该内部类的实例对象并调用其中定义的方法)方法内部类也可以访问外部类的成员变量。方法内部类也可以访问方法体中的局部变量,但是,该局部变量前必须加final修饰符。
  4. 匿名内部类
    在多态中,如果方法的参数被定义为一个接口类型,那么就需要定义一个类来实现接口,并根据该类进行对象实例化。除此之外,还可以使用匿名内部类来实现接口
    匿名内部类格式:
    new 父类(参数列表)或 父接口(){
    //匿名内部类实现部分
    }
    举例理解:
    Interface Animal{
    void shout(); //定义动物类接口
    }
    public class Test{
    //定义匿名内部类作为参数传递给animalShout()方法
    animalShout(new Animal() {
    //实现shout()方法
    public void shout(){
    System.out.println(“喵喵喵…”);
    }
    });
    //定义静态方法animalShout()
    public static void animalShout(Animal an){
    an.shout(); //调用传入对象an的shout()方法
    }
    }
    分两步来理解匿名内部类:
    1.在调用animalShout()方法时,在方法的参数位置写上new Animal(){},这相当于创建了一个实例对象,并将对象作为参数传给animalShout()方法。在new Animal()后面有一对大括号,表示创建的对象为Animal的子类实例,该子类是匿名的。
    2.在大括号中编写匿名子类的实现代码。

8. super关键字

问题描述:
当子类重写父类方法后,子类对象将无法访问父类被重写的方法。为解决此问题,在Java中专门提供了一个super关键字用于访问父类的成员。
super的2种用法:
使用super关键字调用父类的成员变量和成员方法。
格式:super.成员变量
super.成员方法([参数1,参数2……])
使用super关键字调用父类的构造方法。
格式:super([参数1,参数2…….])
这里有坑:使用super调用父类构造方法的代码必须位于子类构造方法的第一行,并且只能出现一次。
定义一个类时,如果没有特殊要求,尽量在类中定义一个无参构造方法,避免被继承时出现错误。因为在子类的构造方法中一定会调用父类的某个构造方法,此时可以在子类的构造方法中通过super关键字指定调用父类的哪个构造方法,如果没有指定,在实例化子类对象时,会自动调用父类的无参构造方法。

9. final关键字

final关键字可用于修饰类、变量和方法,它有“无法改变”或者“最终”的含义,因此被final修饰的类、变量、方法将具有一些特性:
final修饰的类不能被继承
final修饰的方法不能被子类重写(当在父类中定义某个方法,如果不希望被子类重写,可使用final关键字修饰该方法)
final修饰的变量(成员变量和局部变量)是常量,只能赋值一次,一旦被赋值,其值不能改变。final修饰成员变量时,虚拟机不会对它进行初始化。因此使用final修饰成员变量时,需要在定义变量的同时赋初始值

10. 抽象类和接口的区别

抽象类:含有abstract修饰符的类即为抽象类,抽象类不能创建实例对象。含有抽象方法的类必须定义为抽象类,但抽象类中的方法不必是抽象的。抽象类中定义的抽象方法必须在具体子类中实现,所以不能有抽象构造方法或抽象静态方法,如果子类没有实现抽象父类的所有抽象方法,那么子类也必须定义为抽象类。
接口:抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法默认是public abstract类型,接口中的成员变量默认是public static final类型。
二者语法区别:
1.抽象类可以有构造方法,接口中不能有构造方法。
2.抽象类中可以有普通成员变量,接口中没有普通成员变量。
3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
4.抽象类中的抽象方法的访问控制类型可以是public protected default,但接口中的抽象方法只能是public类型的,并且默就是 public abstract类型。
5.抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中的变量只能是public static final类型,并且默认即为public static final类型。
6.抽象类中可以包含普通静态方法,接口中不能包含普通静态方法。
7.一个类可以实现多个接口,但只能继承一个抽象类。
二者应用区别:
接口作用于系统架构设计方面,用于定义模块之间的通信契约。而抽象类作用于代码实现方面,用于实现代码的重用。模板方法设计模式是抽象类的一个典型应用,假设某个项目的所有Servlet类都要用相同的方式进行权限判断,记录访问日志和处理异常,那么可以定义一个抽象的基类,让所有的Servlet都继承这个抽象基类,在抽象基类的service方法中实现记录访问日志、权限判断和处理异常,在各个子类中只是完成各自的业务逻辑代码,伪代码如下:

public abstract class BaseServlet extends HttpServlet{
	public final void service(HttpServletRequest request,HttpServletResponse response) throws IOException,ServletException{
	记录访问日志;
	权限判断;
	   if(具有权限){
	        	try{
				      doService(request,response);
		           }catch(Exception e){
				       记录异常信息
	            	}
	    }
	}
	protected abstract void doService(HttpServletRequest request,HttpServletResponse response) throws IOException,ServletException;
}

public class MyServlet1 extends BaseServlet{
	protected void doService(HttpServletRequest request,HttpServletResponse response) throws IOException,ServletException{
			本Servlet只处理具体业务逻辑代码;
	}
}

11. Java中的异常

Java语言引入了异常类,以异常类的形式对这些非正常情况进行封装,通过异常处理机制对程序运行时发生的各种问题进行处理。Java中提供的异常类都继承自java.lang.Throwable类,Throwable有两个直接子类Error和Exception,其中Error代表程序中产生的错误,Exception代表程序中产生的异常。
1.Error类称错误类,它表示Java运行时产生的系统内部错误或资源耗尽的错误,比较严重,仅靠修改程序本身是不能恢复执行的。(如:使用java命令去运行一个不存在的类就会出现Error错误(虚拟机无法找到,抛出“找不到或无法加载朱磊”))
2.Exception类称异常类,它表示程序本身可以处理的错误。在Exception类的众多子类中有一个特殊的RuntimeException类,该类及其子类(ArithmeticException、ClassCastException、其他子类)用于表示运行时异常,除了此类,Exception类下所有其他的子类都用于表示编译时异常。

12. Java中的访问控制级别

针对类、成员方法和属性提供了四种访问级别,分别是private(类访问级别)、default(包访问级别)、protected(子类访问级别)和public(公共访问级别).这四种控制级别由小到大依次列出。
类访问级别:如果类的成员被private访问控制符修饰,则这个成员只能被该类的其他成员访问,其他类无法直接访问。类的良好封装就是通过private关键字来实现的。
包访问级别:如果一个类或类的成员不使用任何访问控制符修饰,则称它为默认访问控制级别,这个类或者类的成员只能被本包中的其他类访问。
子类访问级别:如果一个类的成员被protected访问控制符修饰,这个成员既能被同一包下的其他类访问,也能被不同包下该类的子类访问。
公共访问级别:这是一个最宽松的访问控制级别,如果一个类或者类的成员被public访问控制符修饰,那么这个类或者类的成员能被所有的类访问,不管访问类与被访问类是否在同一个包中。

11. 字符编码:

计算机之间,无法直接传输一个个的字符,而只能传输二进制数据。为了使发送的字符能以二进制数据的形式进行传输,因此每个国家都制定了自己的字符集(字符码表),它将每一个字符和一个唯一的数字对应而形成的一张表。最常用的字符码表是utf-8,通过选择合适的码表就能完成字符和二进制数据之间的转换,从而实现数据的传输。

  1. 字符编码和解码:
    Java编程中,经常会出现字符转换为字节或者字节转换为字符的操作,这两种操作涉及到两个概念,编码(Encode)和解码(Decode)。一般来说,把字符串转换成计算机能识别的字节序列成为编码,而把字节序列转换为普通人能看懂的明文字符串成为解码。
    在计算机程序中,如果要把字节数组转换为字符串,可以通过String类的构造方法String(byte[] bytes,String charsetName)把字节数组按照指定的字符码表解码成字符串(如果没有指定字符码表,则用操作系统默认的字符码表,如中文的Windows系统默认使用的字符码表是GBK,可以修改为其他的码表,如utf-8);反之,可以通过String类中的getBytes(String charsetName)方法把字符串按照指定的码表编码成字节数组。
package com.test;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class MainTest {

   public static void main(String[] args) throws Exception {
//		String str ="您好";
//		byte[] b1 = str.getBytes();//使用默认的码表编码
//		byte[] b2 = str.getBytes("GBK");//使用GBK编码
//		System.out.println(Arrays.toString(b1));//打印出字节数组的字符串形式
//		System.out.println(Arrays.toString(b2));
//		byte[] b3 = str.getBytes("utf-8");//使用utf-8编码
//		String result1 = new String(b1,"utf-8");
//		System.out.println(result1);
//		String result2 = new String(b2,"GBK");
//		System.out.println(result2);
//		String result3 = new String(b3,"utf-8");
//		System.out.println(result3);
//		String result4 = new String(b2,"ISO8859-1");
//		System.out.println(result4);
   	//怎样解决由于编码和解码时使用的码表不一致所造成的乱码问题?
   	String str = "您好";
   	byte[] b = str.getBytes("GBK");
   	String temp = new String(b,"ISO8859-1");//用错误的码表解码,打印出乱码
   	System.out.println(temp);
   	byte[] b1 = temp.getBytes("ISO8859-1");//再使用错误的码表编码,得到与最开始用GBK编码相同的字节
   	String result = new String(b1,"GBK");//使用正确的码表解码
   	System.out.println(result);//打印正确的“您好”
   	//但是!不是每次在解码时用错码表都能用逆向思维的方法来得到正确的结果,
   	//当把例子中的解码时用的错码表由ISO8859-1改为utf-8结果是?俩都是乱码,为啥。。。。。。哪位大牛帮忙解答一下呀?
   }

}

12.异常:

  • 程序在运行过程中发生的非正常状况,如运行时磁盘空间不足,网络连接中断,被装载的类不存在等状况。针对这种情况,Java语言引入了异常,以异常类的形式对这些非正常状况进行封装,通过异常处理机制对程序运行时发生的各种问题进行处理。Java对异常进行了分类,不同类型的异常分别用不同的Java类表示,所有异常类都继承自java.lang.Throwable类,Throwable下面有派生了俩子类Error和Exception。
  • Error和Exception的区别:
    Error代表程序中产生的错误,Exception代表程序中产生的异常。
    Error类称错误类,它表示Java运行时产生的系统内部错误或资源耗尽的错误(如内存溢出、线程死锁等系统问题),靠修改程序本身是不能恢复的。(如使用java命令去运行一个不存在的类就会出现Error错误。)
    Exception类称异常类,它表示程序本身可以处理的错误,Java程序中进行的异常处理都是针对Exception类及其子类。在Exception类的众多子类中有一个特殊的RuntimeException类,该类及其子类用于表示运行时异常,除了此类,Exception类下所有其他子类都表示编译时异常。
  • Exception类下的编译时异常和运行时异常:
    1.编译时异常(checked异常):
    在java中,Exception类中除了RuntimeException类及其子类都是编译时异常。编译时异常的特点是Java编译器会对其检查,如果出现异常就必须对异常进行处理(try…catch捕获异常;throws声明抛出异常,调用者对其处理),否则程序无法通过编译。(常见编译时异常:网络断线,硬盘空间不够。都是用户能够克服的问题)
    2.运行时异常(unchecded异常):
    RuntimeException类及其子类都是运行时异常。运行时异常的特点是Java编译器不会对其进行检查,编译器不强制要求处理这种异常,即程序运行时产生这种异常,即使不编写异常处理代码,依然可以通过编译。运行时异常一般是由程序中的逻辑错误引起的(软件开发人员考虑不周),程序运行时无法恢复(软件使用者无法克服和恢复)。(常见运行时异常:数组脚标越界(ArrayIndexOutOfBoundsException)、空指针异常(NullPointerException)、类转换异常(ClassCastException)、算数异常(ArithmeticException))
  • 自定义异常类必须继承自Exception或其子类
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同,源码配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值