- java基础编程
- 须知常识
- 区分 | 与 ||
- 区分&与&&
- Scanner输入
- 获取随机数
- swith表达式
- jvm内存
- EclipseDebug
- 单元测试
- 面向对象
- JavaBean
- 包装类
- 类内部结构
- 属性
- 方法
- 构造器
- 代码块
- 内部类
- java特性
- 封装性
- 继承性
- 重写
- 多态性
- 关键字
- this
- final
- abstract
- interface
- super
- static
- instanceof
- Object
- equals
- toString
- 设计模式
- 单例设计模式
- 饿汉式
- 懒汉式
- MVC设计模式
- 代理模式
- 工厂模式
- 异常
- 过程一:(抛)
- 过程二:(抓)
相同点1:运算结果相同
相同点2:当符号左边是false时,二者都会执行符号右边的运算
不同点1:当符号左边是true时,|继续执行符号右边的运算,而||不再执行符号右边的运算
区分&与&&相同点1:运算结果相同
相同点2:当符号左边是true时,二者都会执行符号右边的运算
不同点: 当符号左边是false时,&继续执行符号右边的运算,而&&不再执行符号右边的运算
Scanner输入导包:
import java.util.Scanner;
实例化:
Scanner scan = new Scanner(System.in);
读取:
int n = scan.nextInt(); scan.next(); //String scan.nextInt(); scan.nextDouble(); scan.nextBoolean();获取随机数
Math.random()会返回一个[0,1)之间的小数,可根据需求进行 *** 作
int n = (int)(Math.random() * 90 + 10); //[10,100]swith表达式
在swith结构中的case表达式,只能是如下的6种数据类型之一:
byte、short、char、int、枚举类型、String,且只能是常量
jvm内存 jvm内存包括栈(局部变量)、堆(对象)、方法区(常量池(string)、静态域(static))
EclipseDebug步骤:
-
选中当前工程,右键build path - add libraries - Junit 4 - 下一步
-
创建Java类,进行单元测试
此类是public的,且提供public的无参构造器
-
此类中声明单元测试方法
方法的权限是public的,没有返回值,没有形参
-
此单元测试方法上需要声明注解:@Test,并在单元测试类中导入import org.junit.Test;
-
生命好单元测试方法后,左键双击选中单元测试方法名,右键run as - JUnit Test
简化版:直接在类中@Test声明方法,根据提示自动导入包
面向对象 JavaBeanJavaBean是一种可重用组件,指符合如下标准的Java类:
- 类是公共的 public Xxx{}
- 有一个无参的公共的构造器 public Xxx(){}
- 有属性,且属性有对应的get、set方法
用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以用Java代码创造的对象进行打包,并且其他的开发者可以通过内部的jsp页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。
包装类基本数据类型——>包装类:调用包装类的构造器
Integer n = new Integer(100);
包装类——>基本数据类型:调用包装类Xxx的xxxValue()
int m = n.intVlue();
自动装箱与自动拆箱:
int num = 2; Integer num1 = num; //自动装箱 int num2 = num1; //自动拆箱
基本数据类型、包装类——>String类型,调用String的valueOf(Xxx xxx)方法
String str = String.valueOf(num);
String类型——>基本数据类型、包装类,调用包装类Xxx.parseXxx()方法
int num3 = Integer.parseInt(str);
Integer内部定义了IntegerCache结构,其中定义了Integer[],保存了-128127的证书,如果使用自动装箱的方式,给Integer赋值的范围在-128127时,就可以直接使用数组中的元素,不用再new。目的:提高效率
类内部结构 属性 方法 构造器- 用来创建对象、初始化对象属性
- 如果没有显示声明,系统默认提供一个空参数的构造器;一旦定义,系统就不提供空参构造器
- 构造器权限默认与类相同
- 构造器可以重载(不同参数列表)
属性赋值的先后顺序:
①默认初始化
②显式初始化
③构造器中初始化
④对象.方法、对象.属性 赋值
代码块用来初始化类、对象
根据有无修饰符static可分为静态代码块和非静态代码块
如果一个类中定义多个代码块,则按照声明的先后顺序执行
静态代码块:
- 内部可以有输出语句
- 随着类的加载而执行,并且只执行一次
- 作用:在加载类时初始化类的信息
- 静态代码块的执行优先于菲静态代码块的执行(类的加载优先于对象的创建)
- 静态代码块中只能调用静态属性、方法,不能调用非静态结构
非静态代码块:
- 内部可以有输出语句
- 随着对象的创建而执行,每创建一个对象就执行一次
- 作用:在创建对象时,初始化对象的属性
- 菲静态代码块中可以调用静态和非静态的结构
可以对属性赋值的位置的先后顺序:
- 默认初始化
- 显式初始化 / 代码块中赋值(看谁写在上面)
- 构造器中初始化
- 对象创建后,“对象.属性”赋值
将一个类A声明在另一个类B中,类A称为内部类,类B称为外部类
-
成员内部类(静态、非静态)
-
一方面作为外部类的成员:
- 可以调用外部类的结构
- 可以被static、权限修饰符修饰
-
另一方面作为一个类:
-
可以定义属性、方法、构造器等
-
可以被final、abstract修饰
-
-
-
局部内部类(方法内,代码块内,构造器内)
class Person{ String name; //静态成员内部类 static class Dog{ String name; int age; public void show(){ .... } } //非静态成员内部类 class Bird{ public void display(String name){ sysout(name); //方法的形参 sysout(this.name); //内部类的属性 sysout(Person.this.name); //外部类的属性 } } public void method(){ //方法中的局部内部类 class AA{ } } public Person(){ //构造器中的局部内部类 class BB{ } } { //代码块中的局部内部类 class CC{ } } }
public static void main(String []args){ //创建静态成员内部类 Person.Dog dog = new Person.Dog(); dog.show(); //创建非静态的成员内部类 Person p = new Person(); Person.Bird bird = p.new Bird(); }
内部类在编译后都会生成字节码文件
格式:
- 成员内部类:外部类$内部类名.class
- 局部内部类:外部类$数字 内部类名.class
将 *** 作对象数据结构的内部行为封装起来,只对外暴露几个方法。
将类的属性xxx私有化(private),同时提供公共的(public)方法来获取和设置该属性的值。
权限修饰符
类的属性:可见性依次提高(private、缺省、protected、public
类:可见性依次提高(缺省、public
一、优点
- 减少了代码冗余,提高了代码复用性
- 便于功能扩展
- 为多态性的使用提供了前提
二、格式
class A extends B{ }
A:子类、派生类、subclass
B:父类、超类、基类、superclass
子类自动继承父类中声明的结构:属性、方法
注:子类也会继承父类中private的结构,只是因为封装性的影响,使子类不能直接调用父类的私有结构
三、规定
- 一个类可以被多个子类继承
- 一个类只能有一个父类
- 子父类是相对的概念
- 所有java类都直接或间接的继承java.lang.Object类
-
子类可以重写父类中声明过的方法,方法名和形参列表相同
-
子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符
注:子类不能重写父类中private的方法
-
父类被重写方法返回值类型是void,则子类重写方法返回值类型只能是void
父类被重写方法返回值类型是A,则子类重写方法返回值类型只能是A或A的子类
-
子类重写方法抛出的异常类型不大于父类被重写方法抛出的异常类型
多态性:可以理解为一个事物的多种形态
对象的多态性:父类的引用指向子类的对象
多态的使用:当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法。(虚拟方法调用)
在编译期只能调用父类声明的方法,但在运行期实际执行的是子类重写父类的方法
总结:编译看左边;运行看右边
多态性使用前提:类的继承、方法的重写
对象的多态性只适用于方法,不适用于属性
虚拟方法调用:子类定义了与父类同名同参的方法,在多态情况下,将父类的此方法称为虚拟方法,父类根据付给它的不同子类对象,动态调用属于各子类的该方法。这样的方法调用在编译期间是无法确定的。所以多态不是编译时行为,而是运行时行为。
有了对象的多态性后,父类 xx = new 子类() 时内存中实际上是加载了子类特有的结构的,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法,子类特有的属性和方法不能调用。
如何才能调用子类特有的属性和方法?向下转型,使用强制类型转换符
子类 yy = (子类) xx
面试题:多态性理解
- 实现代码通用性
- 举例:Object的equals方法、JDBC *** 作数据库创建的连接等对象(MySQL、SQL Server、Oracle…
- 抽象类、接口的使用
this表示当前对象。
在类的方法或构造器中,使用this.属性可以区分对象属性与形参
在类的构造器中,使用this(形参列表)调用本类中其它构造器降低代码冗余性
finalfinal:最终的
final可以修饰:类、方法、变量
- final修饰类:此类不能被其他类所继承(如String、System、StringBuffer)
- final修饰方法:此类不可以被子类重写(如Object的getClass())
- final修饰变量:此时变量称为常量,值无法修改
- 可以考虑赋值属性的位置有:显示初始化、代码块中初始化、构造器中初始化(如有多个,每个构造器中都要赋值)
static final可以修饰属性(全局常量)、方法
abstractabstract:抽象的
abstract可以修饰的结构:类、方法
- abstract修饰类:抽象类
- 抽象类不能实例化
- 抽象类中一定有构造器,便于子类实例化时调用(涉及子类对象实例化的全过程)
- 开发中都会创建抽象类的子类,让子类对象实例化完成相关 *** 作
- abstract修饰方法:抽象方法
- 抽象方法只有方法的声明,没有方法体
- 包含抽象方法的类一定是抽象类,反之抽象类中可以没有抽象方法
- 若子类重写了父类中的所有抽象方法,此子类可以实例化
- 若子类没有重写父类所有的抽象方法,此类也是一个抽象类,需要用abstract修饰
注意点:
- abstract不能修饰的结构:属性、构造器
- abstract不能修饰私有方法、静态方法、final的方法、final的类
接口使用interface定义,接口和类是并列的两个结构,接口实际上可以看做是一种规范
类:是不是、接口:能不能
-
JDK7及以前:只能定义全局常量和抽象方法
- 全局常量:public static final,但书写时可以省略
- 抽象方法:public abstract,书写时也可省略
-
JDK8:除了定义全局常量和抽象方法,还可以定义静态方法、默认方法
- 静态方法:public static void methodXxx(){ … }
- 在实现类中只能通过“接口.静态方法”的方式调用静态方法
- 默认方法:public default void methodXxx(){ … }
- 实现类的实例对象可以调用接口中的默认方法,如果重写默认方法,调用时执行的是重写以后的方法
- 如果一个类继承的父类和实现的接口中声明了同名同参数的方法,那么在子类没有重写此方法时,默认调用父类中该方法
- 如果一个类实现了多个接口,多个接口中定义了同名同参数的方法,若实现类不重写该方法,则报错——接口冲突
- 实现类(子类)中调用
- 自己定义的重写的方法:mthod( )
- 父类中声明的方法:super.method( )
- 接口中的默认方法:interfaceA.super.method( )
- 静态方法和默认方法都有方法体
- 静态方法:public static void methodXxx(){ … }
-
接口中不能定义构造器,意味着接口不能实例化
-
接口通过让类去实现(implements)的方式使用,如果实现类实现接口中所有抽象方法,则此类可以实例化;否则此类仍是一个抽象类
-
类可以实现多个接口——弥补了单继承性的局限性
格式:
class AA extends BB implements CC,DD,EE
-
接口之间可以继承,子接口包含父接口中所有的结构:全局常量、抽象方法
interface USB{ void start(); void end(); } class Flash implements USB{ start(){ System.out.println("U盘开始工作"); } end(){ System.out.println("U盘结束工作"); } } class Computer{ public void transferData(USB usb){ usb.start(); usb.end(); } } class test{ Computer com = new Computer(); //创建接口的非匿名实现类的非匿名对象 Flash flash = new Flash(); com.transferData(flash); //创建接口的非匿名实现类的匿名对象 com.transferData(new Flash()); //创建接口的匿名实现类的非匿名对象 USB phone = new USB(){ public void start(){ System.out.println("手机开始工作"); } public void end(){ System.out.println("手机结束工作"); } } com.tansferData(phone); //创建接口的匿名实现类的匿名对象 com.transferData(new USB(){ public void start(){ System.out.println("MP3开始工作"); } public void end(){ System.out.println("MP3结束工作"); } }) }
抽象类与接口的异同点:
- 相同:不能实例化,可以包含抽象方法
- 不同:
- 抽象类:有构造器
- 接口:不能声明构造器
super可理解为:父类的
super可调用:父类的属性、方法、构造器
如果子父类有同名属性,在子类的方法中用this.属性和super.属性可区分开不同属性
在子类构造器中的首行可以显示调用super(形参列表)的方式,调用父类中声明的指定构造器
子类构造器首行可以调用this()以调用其他子类构造器或调用super()调用父类空参构造器
如果在类构造器中首行,没有显式声明this(形参列表)或super(形参列表),则默认调用父类中空参的构造器super()
在类的多个构造器中,至少一个使用了super(形参列表)调用父类的构造器,因此通过子类构造器创建子类对象时,一定会直接或间接的调用父类的空参构造器,进而调用父类的父类的构造器,直到调用了java.lang.Object中的空参构造器为止。所以子类才会拥有父类声明的结构:属性、方法
明确:虽然创建子类对象时,调用了父类构造器,但自始至终就创建过一个对象,即为new的子类对象
staticstatic:静态的,可修饰属性、方法、代码块、内部类
一、使用static修饰的属性:静态变量(类变量)
- 实例变量:创建类的多个对象,每个对象都独立拥有一套类中的非静态属性,各对象实例变量之间互不影响
- 静态变量:创建类的多个对象,每个对象共享一个静态变量,当通过一个对象修改静态变量时,会导致其他对象调用此静态变量时是修改过了的
静态变量随着类的加载而加载,可通过“类.静态变量”的方式调用
静态变量的加载早于对象的创建
由于类只会加载一次,静态变量在内存中也只会存在一份:存在方法区的静态域中
二、使用static修饰的方法:静态方法
- 静态方法中只能调用静态的方法或属性,不能使用this、super关键字
- 非静态方法中,既可以调用非静态也可以调用静态的方法或属性
注:静态属性、方法的生命周期与类相同
三、如何确定是否要static
- 被多个对象所共享的属性设置为static静态属性
- *** 作静态属性的方法通常设置为static
- 工具类中的方法习惯声明为static,比如Math、Arrays、Collections不需要new,直接用类调静态方法
A instanceof B :判断对象A是否是类B或类B的子类的实例,如果是返回true否则false
为了避免在向下转型时出现ClassCastException的异常,在向下转型之前先进性instanceof判断,如果返回true就进行向下转型,否则不转型
Object属性:无
方法:equals()、toString()、getClass()、hashCode()、clone()、finalize()、wait()、notify()、notifyAll()
equals面试题:==和equals()的区别
==:运算法
- 可以使用在基本数据类型和引用数据类型变量中
- 比较基本数据类型变量:比较两个变量保存的数据是否相等(类型不一定要相同)
- 比较引用数据类型变量:比较两个对象的地址值是否相同
equals():方法
- 只适用于引用数据类型变量
- Object类中equals()的定义和运算符==的作用相同,比较两个对象的地址值是否相同
- 像String、Date、File、包装类等都重写了Object类中的equals()方法,重写以后比较的不是两个引用的地址值是否相同,而是比较两个对象的实体内容是否描述
- 自定义的类如果使用equals()比较两个对象的实体内容是否相同,需要进行重写
-
当输出一个对象的引用时,实际上就是调用该对象的toString( )
-
Object类中toString()的定义是
-
String、Date、File、包装类等都重写了Object类的toString()方法,所以输出的不是地址值而是实体内容信息
-
自定义类也可以重写toString()返回对象的实体内容信息
设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。
- 创建型模式(5):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
- 结构型模式(7):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式
- 行为型模式(11):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式
采取一定的方法保证在整个软件系统中,某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。如果要让类在一个虚拟机中只能产生一个对象,首先必须将该类的构造器权限设为private,这样就无法在类的外部new对象,但在类内部仍能创建对象。只能调用该类的静态方法返回类内部创建的对象,静态方法只能访问类中的静态成员变量,因此指向类内部产生的该类对象的变量也必须定义成静态的
- 优点:单例模式只生成一个实例对象,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存
举例:网站计数器、应用程序的日志应用、数据库连接池、读取配置文件的类、windows的任务管理器以及回收站
饿汉式class Bank{ //1.私有化类的构造器 private Bank(){} //2.内部创建类的对象 private static Bank instance = new Bank(); //3.提供公共的静态方法,返回类的对象 public static Bank getInstance(){ return instance; } } main(){ Bank bank1 = Bank.getInstance(); }懒汉式
class Order{ //1.私有化类的构造器 private Order(){} //2.声明当前类的对象 private static Order instance = null; //3.声明返回类的对象的公共静态方法 public static Order getInstance(){ if(instance==null) instance = new Order(); return instance; } }
对比饿汉式、懒汉式
饿汉式:
- 坏处:对象加载时间过长
- 好处:线程安全
懒汉式:
- 好处:延迟对象的创建
- 坏处:线程不安全->多线程时修改为线程安全
将程序分为三个层次:视图模型层veiw、控制器层controller、数据模型层model。这种将程序输入输出、数据处理、以及数据的展示分离开来的设计模式使程序结构变得灵活而清晰,同时也描述了程序各个对象之间的通信方式,降低了程序的耦合性。
代理模式代理模式是Java开发中使用较多的一种设计模式,就是代理类为被代理类提供一种代理以控制对这个对象的访问
静态代理:
interface Network(){ public void browse(); } class Server implements Network{ public void browse(){ //真实的服务器访问网络 } } ckass ProxyServer implements Network{ private Network network; public ProxyServer(Network work){ this.work = work; } public void check(){ //联网之前的检查工作 } public void browse(){ check(); work.browse(); } } class test(){ public static void main(String []args){ Server server = new Server(); ProxyServer proxyServer = new ProxyServer(server); proxyServer.browse(); } }工厂模式
实现了创建者与调用者的分离,即将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的
- 简单工厂模式:用来生产同一等级结构中的任意产品。(对于增加新的产品,需要修改已有代码)
- 工厂方法模式:用来生产同一等级结构中的固定产品。(支持增加任意产品)
- 抽象工厂模式:用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)
Exception:因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理,例如:
- 空指针访问
- 试图读取不存在的文件
- 网络连接中断
- 数组角标越界
异常体系结构:
java.lang.Throwable
- java.lang.Error
- java.lang.Exception
- 编译时异常(checked)必须要处理
- IOException
- FileNotFoundException
- ClassNotFoundException
- IOException
- RuntimeException 运行时异常(unchecked) 可以不处理
- NullPointerException
- ArrayIndexOutOfBoundsException
- ClassCastException
- NumberFormatException
- InputMismatchException
- ArithmeticException
- 编译时异常(checked)必须要处理
异常处理方式:抓抛模型
过程一:(抛) 程序在正常执行过程中,一旦出现异常就在异常代码出生成一个对映异常类的对象,并将此对象抛出,抛出后其后代码不再执行
异常对象的产生方式:①系统自动生成的异常对象
②手动生成一个异常对象并抛出(throw)throw new XxxException(“xxx出错”);
过程二:(抓)-
方式一:try-catch-finally
try{ //可能出现异常的代码 }catch(异常类型1 变量名1){ //异常1的处理方式 }cath(异常类型2 变量名2){ //异常2的处理方式 }... finally{ //最后一定会执行的代码(finally是可选的) }
- 使用try将可能出现异常的代码包装起来,在执行过程中,一旦出现异常就会生成一个对应异常类的对象,根据此对象的类型去catch中进行匹配
- 一旦try中的异常对象匹配到某一个catch时,就进入catch中进行异常的处理,处理完成后就跳出当前的try-catch结构,如有finally就执行finally,没有就继续执行try-catch结构后的代码
- catch中的异常类如果满足子父类关系,则子类一定要声明到父类上方,否则报错
- 常用的异常对象处理方式:①String getMessage() ②printStackTrace()
- finally中声明的是一定会执行的代码,即使catch中又出现异常、try有return、catch有return语句等情况
- 像数据库连接、输入输出流、网络编程Socket等资源,JVM是不能自动回收的,需要自己手动进行资源的释放,释放需要声明在finally中
- 开发中,由于运行时异常比较常见,通常不针对运行时异常写try-catch了,针对编译时异常,一定要考虑异常的处理
-
方式二:throws + 异常类型
- throtw+异常类型 写在方法声明处,指明此方法执行时可能会抛出的异常类型
- 一旦方法执行时出现异常,仍会在异常代码处生成一个异常类的对象,当此对象满足throws后的异常类型时,就会被抛出,异常代码后续的代码就不再执行
对比:try-catch-finally真正将异常给处理掉了
throws的方式只是将异常抛给了方法的调用者,并没有真正将异常处理掉
方法重写的规则之一:子类重写方法抛出的异常类型不大于父类被重写方法抛出的异常类型
Question:开发中如何选择try-catch还是throws?
- 如果父类中被重写的方法没有throws方式处理异常,则子类重写的方法也不能使用throws,也就是如果子类重写方法中有异常,需要用try-catch方式处理
- 执行的方法A中先后又调用了另外几个方法,这几个方法是递进关系执行的,建议这几个方法使用throws异常的方式处理,而方法A可以使用try-catch方式进行处理
面试题:throw和throws区别
throw:表示抛出一个异常类的对象,生成异常对象的过程。声明在方法体内
throws:属于异常处理的一种方式,声明在方法的声明处
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)