当前位置: 首页 > news >正文

用凡科做网站的费用网站建设自动适应功能

用凡科做网站的费用,网站建设自动适应功能,苍南公司网站建设,win7下如何建设网站Java面向对象 面对对象概述#xff0c;类与对象#xff0c;继承#xff0c;重写与重载#xff0c;多态#xff0c;抽象#xff0c;封装#xff0c;包#xff0c;泛型#xff0c;异常 面对对象概述 什么是面向对象#xff08;OOP#xff09; 面向对象(Object Ori…Java面向对象 面对对象概述类与对象继承重写与重载多态抽象封装包泛型异常 面对对象概述 什么是面向对象OOP 面向对象(Object Oriented)是软件开发方法。面向对象的概念和应用已超越了程序设计和软件开发是一种对现实世界理解和抽象的方法是计算机编程技术发展到一定阶段后的产物。 面向过程和面向对象 面向过程 **优点**性能比面向对象好因为类调用时需要实例化开销比较大比较消耗资源。 缺点不易维护、不易复用、不易扩展 面向对象 **优点**易维护、易复用、易扩展由于面向对象有封装、继承、多态性的特性可以设计出低耦合的系统使系统 更加灵活、更加易于维护 **缺点**性能比面向过程差 区别 面向对象是相对于面向过程来讲的指的是把 相关的数据和方法组织为一个整体 来看待从更高的层次来进行系统建模更贴近事物的自然运行模式。 面向过程是具体化的流程化的解决一个问题你需要一步一步的分析一步一步的实现。 面向对象是模型化的你只需抽象出一个类这是一个封闭的盒子在这里你拥有数据也拥有解决问题的方法。需要什么功能直接使用就可以了不必去一步一步的实现至于这个功能是如何实现的管我们什么事我们会用就可以了。 面向对象的底层其实还是面向过程把面向过程抽象成类然后封装方便我们使用的就是面向对象了。 面向对象核心概念 面向对象的三大特性 封装 隐藏对象的属性和实现细节仅对外提供公共访问方式 将变化隔离便于使用提高复用性和安全性。 继承 对于若干个相同或者相识的类我们可以抽象出他们共有的行为或者属相并将其定义成一个父类或者超类然后用这些类继承该父类他们不仅可以拥有父类的属性、方法还可以定义自己独有的属性或者方法。 继承是使用已存在的类的定义作为基础建立新类的技术新类的定义可以增加新的数据或者新的功能也可以使用父类的功能但不能选择性地继承父类。通过使用继承我们可以非常方便地复用以前的代码。 多态 所谓多态就是指程序中定义的引用变量的指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定而是在程序运行期间才确定即一个引用变量到底就会指向那个类的实例对象该引用变量发出的方法调用到底是那个类中实现的方法必须在由程序运行期间才能决定。 在Java中有两种形式可以实现多态继承多个子类对同一方法的重写和接口实现接口并覆盖接口中同一方法。 父类或接口定义的引用变量可以指向子类或具体实现类的实例对象提高了程序的拓展性。 面向对象三大思想 面向对象思想从概念上讲分为以下三种OOA、OOD、OOP OOA面向对象分析Object Oriented Analysis OOD面向对象设计Object Oriented Design OOP面向对象程序Object Oriented Programming 五大基本原则 单一职责原则SRP(Single Responsibility Principle) 类的功能要单一不能包罗万象跟杂货铺似的。 开放封闭原则OCP(OpenClose Principle) 一个模块对于拓展是开放的对于修改是封闭的想要增加功能热烈欢迎想要修改哼一万个不乐意。 里式替换原则LSP(the Liskov Substitution Principle LSP) 子类可以替换父类出现在父类能够出现的任何地方。比如你能代表你爸去你姥姥家干活。哈哈~~ 依赖倒置原则DIP(the Dependency Inversion Principle DIP) 高层次的模块不应该依赖于低层次的模块他们都应该依赖于抽象。抽象不应该依赖于具体实现具体实现应该依赖于抽象。就是你出国要说你是中国人而不能说你是哪个村子的。比如说中国人是抽象的下面有具体的xx省xx市xx县。你要依赖的抽象是中国人而不是你是xx村的。 接口分离原则ISP(the Interface Segregation Principle ISP) 设计时采用多个与特定客户类有关的接口比采用一个通用的接口要好。就比如一个手机拥有打电话看视频玩游戏等功能把这几个功能拆分成不同的接口比在一个接口里要好的多。 小结 抽象会使复杂的问题更加简单化。 从以前面向过程的执行者变成了张张嘴的指挥者。 面向对象更符合人类的思维面向过程则是机器的思想 类与对象 概述 类 类是具有相同属性和服务的一组对象的集合。为属于该类的所有对象提供了统一的抽象描述其内部包括属性和服务两个主要部分。在面向对象的编程语言中类是一个独立的程序单位应该有一个类名并包括属性说明和服务说明两个主要部分。 对象对象是系统中用来描述客观事物的一个实体是构成系统的一个基本单位。一个对象由一组属性和对这组属性进行操作的一组服务组成。从更抽象的角度来说对象是问题域或实现域中某些事物的一个抽象它反映该事物在系统中需要保存的信息和发挥的作用它是一组属性和有权对这些属性进行操作的一组服务的封装体。客观世界是由对象和对象之间的联系组成的。 类与对象的关系 类是一组相关属性和行为的集合 对象该类事物的具体体现 类 Java中用class描述事物也是如此 1.成员变量 就是事物的属性 2.成员方法 就是事物的行为 定义类其实就是定义类的成员(成员变量和成员方法) 成员变量和局部变量的区别 成员变量 类中的属性称为成员变量该变量定义时 格式为 数据类型 变量名; 注意 ① 在类中定义的成员变量并不需要有初始值 ② 对于成员变量来说其作用域是在整个类中有效 何为局部变量 局部变量就是方法里定义的变量。局部变量仅作用在局部区域中从定义开始到大括号或者return结束生命周期短。局部变量存储基本数据类型变量放在栈中引用数据类型放在堆中局部变量可以先定义再初始化也可以定义的同时初始化局部变量没有默认初始值。 在类中的位置不同 成员变量 类中方法外 局部变量 方法内或者方法声明上 在内存中的位置不同 成员变量 堆内存 局部变量 栈内存 生命周期不同 成员变量 随着对象的存在而存在随着对象的消失而消失 局部变量 随着方法的调用而存在随着方法的调用完毕而消失 初始化值不同 成员变量 有默认的初始化值 局部变量 没有默认的初始化值必须先定义赋值才能使用。 类的初始化过程 Student s new Student();在内存中做了哪些事情? 加载Student.class文件进内存 在栈内存为s开辟空间 在堆内存为学生对象开辟空间 对学生对象的成员变量进行默认初始化 .对学生对象的成员变量进行显示初始化 通过构造方法对学生对象的成员变量赋值 学生对象初始化完毕把对象地址赋值给s变量 对象的内存图 方法的构造 问题1.对于创建一个对象格式为new 类名() 格式的解释 对于类名()方法的调用 类名()方法是什么2.对于当前的类对象赋予其属性值相对较为麻烦有没有更好的方式编写对应的代码构造方法实际上是一个方法编写构造方法的格式public 类名(){ 无参构造}public 类名(数据类型 参数名,...){ 无参构造}注意① 构造方法的方法名需要和类名名称一致② 构造方法不需要有返回值并且连void都不需要编译和反编译编辑将.java文件信息编译成进制文件反编译将进制文件 转换成文本文件 idea提供了反编译的功能对于.class文件可以直接查看其内容通过idea查看StuConstruct类的编译文件 可以发现有对应的构造方法public StuConstruct() {匿名对象 匿名对象就是没有名字的对象。 是对象的一种简化表示形式 匿名对象的两种使用情况 对象调用方法仅仅一次的时候 作为实际参数传递static关键字 可以修饰成员变量和成员方法 static关键字特点 随着类的加载而加载 优先于对象存在 被类的所有对象共享 这也是我们判断是否使用静态关键字的条件 可以通过类名调用 static关键字注意事项 在静态方法中是没有this关键字的 静态方法只能访问静态的成员变量和静态的成员方法 修饰成员属性 static修饰成员属性① 对象可以调用static修饰的成员变量 并可以对其进行赋值② 通过static修饰的成员变量是所有对象所共有的属性③ 通过static修饰的成员变量是可以通过类名.属性名进行调用 赋值(赋值过后只要不再次赋值值为最新一次赋的值)④ 通过内存展示static修饰的成员变量修饰成员方法 成员方法是属于对象的 静态方法 属于对象也属于类的 静态方法① 可以被对象进行调用② 可以直接使用类名进行调用③ 在成员方法中可以直接调用静态的方法④ 在静态方法中不能直接调用成员方法 为什么?当静态方法被调用时可能是对象调用 也可能是类进行调用当是类调用时并没有获取到一个对象所以不能直接进行使用类进行调用成员方法⑤ 成员方法只能通过对象进行调用而不能通过类名进行调用⑥ 对于静态方法中可以直接使用静态属性⑦ 对于静态方法中不能使用成员属性 制作工具类 制作工具类 ArrayTools 制作帮助文档(API) javadoc -d 目录 -author -version ArrayTool.java 工具类将一些常用的方法该方法可以被static修饰放置一个类中进行保存之后如果使用相关的方法可以直接使用类名.方法进行调用代码块 构造代码块 构造代码块是在构造方法之前执行 形式在类中方法外使用{}进行定义 在每个对象被创建时调用类在调用时并不会执行构造代码块 静态代码块 会随着类的加载而被执行 形式在类中方法外使用static{}进行定义 当类被加载时会默认先执行其静态代码块智慧再去执行构造代码块并且静态代码块只会执行一次 原因当程序运行时会将当前的.class文件加载到方法区中的class文件区在整个过程中只需要加载一次所以静态代码块只会执行一次 局部代码块 当类中的方法被执行时才会执行 形式在方法中使用{}进行定义 作用限定变量的作用范围当在{}内定义的变量不能在{}外进行使用当{}代码块执行完成该变量会被销毁该方式用于代码优化当{}执行完成变量的内存空间也会被释放 同步代码块 多线程阶段在讲 为什么会需要有如上类型的代码块 当使用工具类时可以直接使用类名静态方法进行调用此时对于一些静态变量如果需要做初始化赋值此时没有一个比较不错的方式于是可以定义一个静态代码块当类被加载时可以执行相对应的代码块内容 于是在该代码块中就可以实现静态变量的初始化 当对象被构建时在构造方法执行之前可能需要做一些环境的初始化工资于是可以定义构造代码块比如要创建对象操作Mysql中的此时可以直接使用构造代码块从给定的配置信息中读取连接信息进行链接当构造代码块执行完成后可以获取一个对象 静态代码块、构造代码块、构造函数执行顺序 父类静态代码块 子类静态代码块 main()方法 父类构造代码块 父类构造器方法 子类构造代码块 子类构造器方法 形式参数问题 基本类型作为形式参数 : 基本类型作为参数传递的时候是在一个方法栈中开辟了一块新内存拷贝了原来的数据值所以无论我们如何修改原来的数据值不会受到任何影响。 引用类型作为形式参数 : 首先我们要知道引用的数据存储在栈内存中而引用指向的对象存储在堆内存中。 当引用作为方法参数传递给方法的时候是将引用的值拷贝一份给另一个引用但引用指向的都是同一个堆内存所以进行的修改操作同样有效。 引用类型中形参能够改变实参的值或者一个引用能够改变另一个引用的值仅仅是因为他们栈内存中存储的值相同但这个值是随时可以修改的。 实例 public class Practice2 {public static void main(String[] args) {// TODO Auto-generated method stubint a 5;System.out.println(a);//5change(a);System.out.println(a);//5}public static void change(int b) {b 500;} } ---------------------------------- public class Practice {static A a new A(10);public static void main(String[] args) {// TODO Auto-generated method stubPractice practice new Practice();System.out.println(practice.a.intData);//10change(practice.a);System.out.println(practice.a.intData);//500}public static void change(A aa) {aa.intData 500;System.out.println(aa.intData);//500} }class A{int intData;public A(int intData) {this.intData intData;}}继承 继承关系 语法 class 子类名 extends 父类名 {} 说明 ① 对于继承关系子类可以获取到父类中的所有属性 ② 对于子类可以存在有自身独特的属性 ③ 对于子类也可以继承父类中的方法 ④ 当子类中对于父类继承过来的方法存在有重名那么在对象调用时根据就近原则调用自身的成员方法 ⑤ 对于一个父类可以存在有多个子类 ⑥ Java中不能实现多继承在子类中只能存在单个的父类 ⑦ 对于现实逻辑来看在类中会存在有多个类之间的关系如何定义多个类关系 Java 虽然不支持多继承但是支持多层继承单继承 ⑧ 继承关系中的构造方法 在创建对象时默认情况下会先去通过extends关键字找到父类中的构造方法并执行其构造方法之后 再去执行子类中的构造方法 要想获取子类对象先创建父类对象 当构造代码块和构造方法都存在时那么会先执行父类中的构造代码块和构造方法再执行子类中的构造代码块和构造方法 静态代码块会先执行将继承关系中所有的类加载完成 - 构造代码块 继承的好处 提高了代码的复用性 多个类相同的成员可以放到同一个类中 提高了代码的维护性 如果功能的代码需要修改修改一处即可 让类与类之间产生了关系是多态的前提 其实这也是继承的一个弊端类的耦合性很强 耦合性 表示代码之间的关系该关系好处是减少代码量坏处是代码修改时 会牵扯过多的子类导致开发复杂难度较大 注意 子类只能继承父类所有非私有的成员(成员方法和成员变量) 什么时候使用继承关系 当两个类存在有is a的关系 而不是一个类中有少量的方法需要获取时继承 出现同名的变量 ① 变量再方法中有就近原则 ② 当子类中有父类同名的变量那么创建子类对象时对应变量赋值会根据就近原则直接赋予给当前对象 查看继承过程中构造方法的相关问题 ① 当子类对象被构建时需要先创建父类中的对象才能有子类对象 问题什么时候创建如何调用的 当类被加载后再去调用构造方法 加载过程是先加载父类之后再加载子类的类对象 当创建子类对象时默认先去寻找父类中的无参构造再由父类无参构造执行执行完成后再去执行子类构造 ② 当父类中无参构造被有参构造覆盖时此时不能通过默认的方式创建对象同时编码不会立即报错该错误是编译时期的错误 ③ 当需要使用父类中的构造方法时可以使用super关键字该关键字和this关键字形式一样this代表当前对象而super代表父类对象 ④ 当子类的构造方法中需要使用super关键字那么必须要放在第一行 为啥 当子类运行构造方法时必须要根据继承关系先运行父类中的构造方法此时必须要将super放在构造方法中的第一行 拓展对于this来说 也可以通过this(参数列表)调用 无参构造或有参构造 类的继承格式 在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的一般形式如下 super 与 this 关键字 super关键字我们可以通过super关键字来实现对父类成员的访问用来引用当前对象的父类。 this关键字指向自己的引用。 super关键字 1super能出现在实例方法和构造方法中。 2super的语法是“super.”和“super()”。 3 super不能出现在静态方法中。 4 super大部分情况下是可以省略的。 5super.什么时候不能省略呢 别急我们想一下this指向的是什么是当前对象自己。super和this类似它指向了当前对象自己的父类型特征也就是继承过来的那些东西。 super和this区别是this可以看做一个引用变量保存了该对象的地址是当前对象整体而super代表的是父类型特征是子类局部的一些东西这些继承过来的东西已经在子类里面了你可以输出整体this但不能输出父类型特征super。因为super指向的东西不是一个整体没法打印输出。 System.out.println(this); //输出this.toString()的值 System.out.println(super); //编译报错需要. 当在子类对象中子类想访问父类的东西可以使用“super.”的方式访问。例如方法覆盖后子类内部虽然重写了父类的方法但子类也想使用一下父类的被覆盖的方法此时可以使用“super.”的方式。当子类中出现和父类一样的属性或者方法此时你要想去调用父类的那个属性或者方法此时“super.”不能省略。 this和super都只能在对象内部使用。 this代表当前对象本身super代表当前对象的父类型特征。 “this.”是一个实例对象内部为了区分实例变量和局部变量。 而“super.”是一个实例对象为了区分是子类的成员还是父类的成员。 父类有子类也有子类想访问父类的“super.”不能省略。 6super()只能出现在构造方法的第一行通过当前的构造方法去调用“父类”中的对应的构造方法目的是创建子类对象时先初始化父类型特征。 用通俗的话来讲要想有儿子得先有父亲。 我问你当构造方法第一行有this()时你还能手动添加“super()”吗显然不行因为“this()”也只能出现在第一行你不能在它前面写任何代码。所以我们又得出一个结论构造方法中“this()”和“super()”不能同时出现也就是“this()”和“super()”都只能出现在构造方法的第一行。上面谈的都是无参数的“super”方法我们也可以在构造方法的第一行使用有参数的“super(父类构造函数的参数列表)”但值得注意的是当子类构造方法执行有参数的“super(参数列表)”方法你得确保父类中也有对应的有参数构造方法不然会编译报错。同样我要提醒一下当子类构造方法的第一行执行super()无参数方法那么父类中一定要有无参数构造方法有的人可能会在父类中写了有参数的构造方法却忽略了写无参数构造方法那么在子类构造方法内就会报错因为当你在一个类中写了有参数的构造方法时无参数构造方法就会不存在你需要自己补上无参数的构造方法这是一个良好的编程习惯。无论你子类构造方法有没有“this()”和“super()”方法实例化子类对象一定一定会执行对应的父类构造方法即不管实例化了一个怎样的孩子它一定会先实例化一个对应的父亲。 先复习一下this关键字的使用。 1this能出现在实例方法和构造方法中 2this的语法是“this.”和“this()” 3this不能出现在静态方法中 4this大部分情况下是可以省略的 5this.什么时候不能省略呢 在区分局部变量和实例变量时不能省略。例如 Public void setName(String name){this.name name; } final关键字 final关键字是最终的意思可以修饰类成员变量成员方法。 修饰类类不能被继承 修饰变量变量就变成了常量只能被赋值一次 修饰方法方法能被继承方法不能被重写 final关键字面试题 final修饰局部变量 在方法内部该变量不可以被改变 在方法声明上分别演示基本类型和引用类型作为参数的情况 基本类型是值不能被改变 引用类型是地址值不能被改变 final修饰变量的初始化时机 在对象构造完毕前即可 需求当前定义的类为最终类不能被其他子类进行继承...在类名中使用 final修饰*//*需求在某些类中某些成员方法不能被子类所修改*//*总结对于final可以修饰 类、成员属性、成员方法修饰类当前类不能被继承形式final class 类名 {}修饰成员属性当前属性为一个常量形式: final 数据类型 常量名注意对于修饰的是一个引用类型那么地址值不能改变但是地址所指向的位置空间数据可以改变修饰成员方法当前方法可以被继承但是不能被修改形式 public final 返回值类型 方法名() {}*/构造器 子类是不继承父类的构造器构造方法或者构造函数的它只是调用隐式或显式。如果父类的构造器带有参数则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。 如果父类构造器没有参数则在子类的构造器中不需要使用 super 关键字调用父类构造器系统会自动调用父类的无参构造器。 实例 package com.test.demo11;public class Test4 {public static void main(String[] args) {System.out.println(------SubClass 类继承------);SubClass sc1 new SubClass();SubClass sc2 new SubClass(100);System.out.println(------SubClass2 类继承------);SubClass2 sc3 new SubClass2();SubClass2 sc4 new SubClass2(200);} } class SuperClass{private int n;SuperClass(){System.out.println(SuperClass());}SuperClass(int n){System.out.println(SuperClass(int n));this.nn;} } class SubClass extends SuperClass{private int n;SubClass(){//自动调用父类的无参构造器System.out.println(SubClass);}public SubClass(int n){super(300);//调用父类中带有参数的构造器System.out.println(SubClass(int n):n);this.nn;} } class SubClass2 extends SuperClass{private int n;SubClass2(){super(300);//调用父类中有参构造System.out.println(SubClass2);}public SubClass2(int n){System.out.println(SubClass2(int n):n);this.nn;} } 结果 ------SubClass 类继承------ SuperClass() SubClass SuperClass(int n) SubClass(int n):100 ------SubClass2 类继承------ SuperClass(int n) SubClass2 SuperClass() SubClass2(int n):200 重写与重载 重写(Override) 重写的前提是继承只有存在继承关系的类之间才存在重写。 重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变核心重写 重写的好处在于子类可以根据需要定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。 重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。例如 父类的一个方法申明了一个检查异常 IOException但是在重写这个方法的时候不能抛出 Exception 异常因为 Exception 是 IOException 的父类只能抛出 IOException 的子类异常。 注意事项 重写方法的不能比被重写的方法有更严格的访问限制 相同的方法名相同的参数列表相同的返回值 重写方法不能抛出比被重写方法声明更广的异常可以抛出范围更小的或不抛出异常 不能重写被final修饰的方法 如果一个方法不能被继承则不能被重写。例如构造器不能被继承所以不能被重写。或者是父类声明为private的方法 子类不能重写父类的构造方法不能重写static修饰的方法。 方法的重写规则 参数列表与被重写方法的参数列表必须完全相同。 返回类型与被重写方法的返回类型可以不相同但是必须是父类返回值的派生类java5 及更早版本返回类型要一样java7 及更高版本可以不同。 访问权限不能比父类中被重写的方法的访问权限更低。例如如果父类的一个方法被声明为 public那么在子类中重写该方法就不能声明为 protected。 父类的成员方法只能被它的子类重写。 声明为 final 的方法不能被重写。 声明为 static 的方法不能被重写但是能够被再次声明。【父类静态方法子类也必须通过静态方法进行重写。(其实这个算不上方法重写但是现象确实如此至于为什么算不上方法重写多态中我会讲解)】 子类和父类在同一个包中那么子类可以重写父类所有方法除了声明为 private 和 final 的方法。 子类和父类不在同一个包中那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。 重写的方法能够抛出任何非强制异常无论被重写的方法是否抛出异常。但是重写的方法不能抛出新的强制性异常或者比被重写方法声明的更广泛的强制性异常反之则可以。 构造方法不能被重写。 如果不能继承一个方法则不能重写这个方法。 重载(Overload) 重载(overloading) 是在一个类里面方法名字相同而参数不同。和返回类型无关。 每个重载的方法或者构造函数都必须有一个独一无二的参数类型列表。 最常用的地方就是构造器的重载。 重载规则: 被重载的方法必须改变参数列表(参数个数或类型不一样) 被重载的方法可以改变返回类型 被重载的方法可以改变访问修饰符 被重载的方法可以声明新的或更广的检查异常 方法能够在同一个类中或者在一个子类中被重载。 无法以返回值类型作为重载函数的区分标准。 如果方法有明确的返回值一定要有return带回一个值 重写与重载之间的区别 方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现重写是父类与子类之间多态性的一种表现重载可以理解成多态的具体表现形式。 (1)方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。 (2)方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。 (3)方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。 多态 多态存在的三个必要条件 继承 重写 父类引用指向子类对象 在逻辑关系上对象可以是由多种描述方式但是前提是对象有对应的继承关系多态将子类对象赋予给父类变量 - 有父类引用指向子类对象前提有继承关系 多态成员访问成员变量编译看左边运行看左边成员方法编译看左边运行看右边静态方法编译看左边运行看左边 多态中的转型向上转型 (多态的形式)从子到父父类引用指向子类对象向下转型从父到子父类引用转为子类对象注意事项当进行做强制类型转换时在运行时会校验当前地址的对象是否和变量的类型存在有继承关系 实例Per per new Stu(); // 将子类的对象赋予给父类变量 从子到父Stu stu1 (Stu) per; // 向下转换 将父类变量强制类型转换为子类变量//上面两行同时有才能像下转型Per tea new Tea(); // 向上转型/*注意: tea中的内存地址实际上是指向一个教师对象现在通过强制转换将 教师对象地址赋予给 Stu stu2 学生变量*/Stu stu2 (Stu) tea; // 强制转换 有类型转换问题Per per new Stu(); // 将子类的对象赋予给父类变量 从子到父//从父到子 Per per new Stu(); Stu stu1 (Stu) per;向上转型和向下转型 对象的向上转型父类 父类对象 子类实例 对象的向下转型子类 子类对象 子类父类实例 示例一 父类强制转子类Father f new Father(); Son s (Son)f;//出错 ClassCastException分析: 创建一个父类的实例想要强制把父类对象转换成子类的不行 通俗的想父亲永远不可能转换成儿子。因为有空白假如转换了那么上幼儿园、哺乳这些儿子的特有属性父亲是没有的强转就出现了ClassCastException示例二 “假的”父类强制转子类Father f new Son(); Son s (Son)f;//可以分析 父类对象引用着一个子类实例。 Son类特有的属性暂时不能通过 f 来操作因为Father类没有Son类子类的特有属性。 接着创建子类对象 s它引用的是父类对象 f 强制转换来的对象其实就是个装爹的Son把他强制转回了Son这时就可以通过 s 来操作子类的特有属性了。通俗的说就是儿子装爹终究是儿子本质没变还是可以把他强制转回儿子的。示例三 子类强制转父类Son s new Son(); Father f (Father)s;//可以分析 子类转换成父类只是子类对象的特有属性无法利用 f 操作f 可以操作其非特有的属性由父类继承而来的属性。也就是说儿子可以执行吃饭和睡觉的方法父亲也有因为这就是从父亲继承的但是让父亲执行上小学的方法就不行因为这是儿子的‘‘特有属性’’。通俗的说儿子和爹的共同点——“都是人”儿子作为人的基本属性是从父亲继承过来的儿子转换成了父亲只是失去了原本自己比父亲多出来的那些特有属性。 抽象类 抽象类 抽象类的定义规则 抽象类和抽象方法都必须用abstract关键字来修饰 抽象类不能被实例化也就是不能用new关键字去产生对象 抽象方法只需声明而不需实现 含有抽象方法的类必须被声明为抽象类抽象类的子类必须复写所有的抽象方法后才能被实例化否则这个子类还是个抽象类 抽象类的定义格式abstract class 类名称 // 定义抽象类{声明数据成员;访问权限 返回值的数据类型 方法名称参数...//定义一般方法{...}abstract 返回值的数据类型 方法名称参数...;//定义抽象方法在抽象方法里没有定义方法体} package com.shujia.day07;import com.shujia.day07.animal.Animal;import com.shujia.day07.animal.Cat;import com.shujia.day07.animal.Dog;import com.shujia.day07.father.GrandFather;import com.shujia.day07.father.Son;public class Demo02Abstract {public static void main(String[] args) {/*什么是抽象:① 从逻辑角度看 是表示一个概念性的东西② 从代码角度来看 表示方法时 该方法只有具体的方法格式而没有实现的代码块public void eat() 抽象的方法抽象类① 从逻辑角度看 用于表示一个 物种的抽象种类 或者是对某个概念总和的抽象比如对于猫和狗都是动物,那么 猫类 狗类 动物类中 动物类是抽象类② 从代码角度来看包含有抽象方法的类称为抽象类对于抽象方法需要和其他方法进行区分于是可以添加abstract进行标记对于包含抽象方法的类需要对其进行标记 可以在类定义时添加 abstract 进行标记定义格式public abstract class 抽象类名{public abstract 返回值类型 方法名(参数列表); // 没有方法体}单独的抽象类并没有实际意义因为抽象方法没有具体的实现所以可以构建类和类之间的关系—— 使用继承于是可以使用 public class 类A extends 抽象类B 由于 class 类A 是一个非抽象类 根据继承关系 得到抽象类B中的抽象方法 但是类A不是抽象类不能包含抽象的方法 于是可以通过重写的方式对其中的抽象方法进行重写并定义其具体的代码块注意1.抽象类不能创建其对象2.抽象类的子类对象可以指向抽象类的变量 多态 父类引用指向子类对象从逻辑上看猫和狗都是属于动物中的一种所以可以使用动物来描述猫和狗3.抽象类中可以有非抽象的方法(逻辑理解) 对于 爷爷类 父亲类, 对于爷爷类来说会有一些未完成的理想但是同时也有一些资产对于父亲类来说继承了爷爷类的资产和理想 对于爷爷类当爷爷去世那么该类就是一个抽象类4.抽象类的子类可以是抽象的也可以是非抽象的对于抽象子类不需要去实现其抽象方法5.类型之间可以存在传递关系爷 父 子 对于子的类的对象 可以使用爷类类型 变量 来接收6.对于抽象类中的变量6.1 可以被子类继承6.2 变量不能使用abstract进行修饰6.3 对于static修饰的变量可以直接使用类名进行调用7.对于继承关系中抽象类继承了另一个抽象父类此时抽象类可以实现父类中的抽象方法也可以不实现其抽象方法8.在抽象类的编译文件中通过反编译可以看到其构造方法为什么有其作用是什么在继承关系中子类如果要创建对象那么需要调用自身的构造方法但是创建之前先去执行父类中的构造方法之后再去执行后续的代码所以父类虽然是一个抽象类但是必须要有其构造方法9.在子类中可以通过super()显示调用父抽象方法中的构造方法注意当编写代码时出现有红色波浪 可以使用 alt enter键 选择idea提供的错误解决方案一个类如果没有抽象方法可不可以定义为抽象类?如果可以有什么意义?可以该抽象类可以用于类之间的逻辑划分抽象类表示的是一个抽象的概念并没有具体的实例abstract 不能和哪些关键字共存private 冲突: abstract修饰的方法是一个抽象方法对于抽象方法来说要使其有意义那么必须通过继承来进行实现如果使用private修饰那么子类无法通过继承来获取到final 冲突: abstract修饰的方法是一个抽象方法对于抽象方法来说要使其有意义那么必须通过继承来进行实现对于继承时如果使用 final的方法 不能对方法进行重写操作static 没有意义: static可以直接通过类进行调用但是当前抽象类中抽象方法没有具体的实现代码块*/// Animal animal new Animal(); // 抽象类中编译时虽然有构造方法但是在该方式中不能创建单独的对象Cat cat new Cat();cat.eat();cat.sleep();Animal animal1 new Cat();animal1.eat();Dog dog new Dog();dog.eat();Animal animal2 new Dog();animal2.eat();// Father father new Father();// long money father.getMoney();// System.out.println(现在有money钱);// father.haveDream();GrandFather son new Son();long money son.getMoney();System.out.println(现在有money钱);son.haveDream();System.out.println(son.sign);System.out.println(GrandFather.NAME);// GrandFather.getMoney(); // static修饰的类可以被抽象类所调用// Father father new Father();}} 接口 接口的定义 接口interface是Java所提供的另一种重要技术它的结构和抽象类非常相似也具有数据成员与抽象方法但它与抽象类又有以下两点不同 接口里的数据成员必须初始化且数据成员均为常量 接口里的方法必须全部声明为abstract也就是说接口不能像抽象类一样保有一般的方法而必须全部是“抽象方法”。 接口定义的语法如下interface 接口名称 // 定义抽象类 { final 数据类型 成员名称 常量 //数据成员必须赋初值 abstract 返回值的数据类型 方法名称参数...; //抽象方法注意在抽象方法里没有定义方法主体 }接口与一般类一样本身也具有数据成员与方法但数据成员一定要赋初值且此值将不能再更改方法也必须是“抽象方法”。也正因为方法必须是抽象方法而没有一般的方法所以抽象方法声明的关键字abstract是可以省略的。 **相同的情况也发生在数据成员身上因数据成员必须赋初值且此值不能再被更改所以声明数据成员的关键字final也可省略。**事实上只要记得 接口里的“抽象方法”只要做声明即可而不用定义其处理的方式 数据成员必须赋初值。 接口的实现 在Java中接口是用于实现多继承的一种机制也是Java设计中最重要的一个环节每一个由接口实现的类必须在类内部复写接口中的抽象方法且可自由地使用接口中的常量。 既然接口里只有抽象方法它只要声明而不用定义处理方式于是自然可以联想到接口也没有办法像一般类一样再用它来创建对象。利用接口打造新的类的过程称之为接口的实现implementation。 接口实现的语法class 类名称 implements 接口A,接口B //接口的实现 { ... }接口的扩展 接口是Java实现多继承的一种机制一个类只能继承一个父类但如果需要一个类继承多个抽象方法的话就明显无法实现所以就出现了接口的概念。一个类只可以继承一个父类但却可以实现多个接口。 接口与一般类一样均可通过扩展的技术来派生出新的接口。原来的接口称为基本接口或父接口派生出的接口称为派生接口或子接口。通过这种机制派生接口不仅可以保留父接口的成员同时也可加入新的成员以满足实际的需要。 同样的接口的扩展或继承也是通过关键字extends来实现的。有趣的是一个接口可以继承多个接口这点与类的继承有所不同。 接口扩展的语法interface 子接口名称 extends 父接口1,父接口2... { ... }package com.shujia.day07;import com.shujia.day07.teacher.Sing; import com.shujia.day07.teacher.TeacherInterface;public class Demo05Interface {public static void main(String[] args) {/*接口接口的意义实际上是对当前的类所属功能进行拓展比如 电脑 通过 USB接口/ HDMI接口 外接其他设备使其具有相对应的一些功能接口在Java中的意义对于有些抽象类其子类中并不是所有的方法都是抽象类所共有的需要通过一些其他的方式再添加一些功能到当前子类中比如教师抽象类中定义的方法 是所有教师子类所都有的但是部分教师都有自身所独特的技能教师A - 唱歌教师B - 唱歌包装唱歌为一个接口每个教师唱歌的风格可能不一样对应唱歌的方法有自己的实现形式教师C - 乐器教师D - 乐器包装乐器为一个接口每个教师掌握的乐器可能不一样对应乐器有自己的实现形式如何定义接口形式:public interface 类名 {}使用单独的关键字对其进行描述为什么接口不能是一个 class 而必须是单独的一种类型注意接口是功能性的拓展是对当前的类给一些独特的 方法规范注意① 对于接口中定义的方法只是一个规范不能存在有具体的方法体具体的方法需要在子类中进行实现② 接口不能构建其对象所以需要借助类来构建并对其进行调用③ 对于接口要通过其子实现类来进行实现其抽象方法使用关键字 implements④ 对于接口中可以定义其属性但是需要对其属性进行赋予初始值接口中的属性一般情况下如果要定义那么经常是以常量的形式存在比如一些配置接口将配置信息设置成一个常量形式⑤ 接口和抽象类的区别方法上的区别抽象类:既可以定义抽象方法也可以定义非抽象方法接口: 只能定义抽象方法存在的意义不同抽象类: 对于一个概念进行做抽象将其相关的属性和方法形成一个类接口: 对当前类的功能进行拓展相当于是电脑的一个外接接口⑥ 从代码设计角度为什么需要接口1. 因为如果使用抽象类来设计接口那么根据Java的定义原则只能存在有单继承或者多层继承的关系不支持多继承于是需要单独设计一个 interface2. 在实际开发过程中对于一个类可能需要实现多个不同的接口而抽象类无法提供⑦ 一个类可以实现多个接口其格式为class 类名 implements 接口1,接口2⑧ 接口可以存在有继承关系,并且接口存在有多继承关系为什么对于接口来说继承以后不能对其方法进行重写那么就不会造成多继承中对于相同方法的不同实现*/// Sing sing new Sing(); // 接口不能构建其对象TeacherInterface teacherInterface new TeacherInterface();teacherInterface.sing(); // System.out.println(teacherInterface.singName);System.out.println(teacherInterface.SING_NAME);teacherInterface.skill();} } 实参和形参 形式参数在方法的参数列表中定义的参数称为形式参数基本类型一般情况下是传递具体的数值给形参,对于形参的计算并不会改变原来的实参引用类型一般情况下是传递内存地址给形参如果对内存地址的变量进行修改那么会改变原来实参的数值实参除形式参数以外的其他参数在一般情况下在方法内进行定义的 返回值 返回值类型基本类型引用类型封装 什么是封装 在面向对象程式设计方法中封装英语Encapsulation是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。 封装可以被认为是一个保护屏障防止该类的代码和数据被外部类定义的代码随机访问。 要访问该类的代码和数据必须通过严格的接口控制。 封装最主要的功能在于我们能修改自己的实现代码而不用修改那些调用我们代码的程序片段。 适当的封装可以让程式码更容易理解与维护也加强了程式码的安全性。 封装概述 是指隐藏对象的属性和实现细节仅对外提供公共访问方式。 好处 隐藏实现细节提供公共的访问方式 提高了代码的复用性 提高安全性。 封装原则 将不需要对外提供的内容都隐藏起来。 把属性隐藏提供公共方法对其访问。 匿名对象 匿名对象就是没有名字的对象。 是对象的一种简化表示形式 匿名对象的两种使用情况 对象调用方法仅仅一次的时候 作为实际参数传递 包 包 ​ 在创建类时会默认给当前类中第一行代码添加 package 路径 用于表示当前类所在的位置 ​ 该位置的作用是在编译时会将当前的.class文件放入指定路径中 ​ 路径是使用.进行分割 ​ 类路径 com.shujia.day08.teacher.Teacher 可以使用idea选中当前类 右键 选择copy Reference 包的作用 1、把功能相似或相关的类或接口组织在同一个包中方便类的查找和使用。 2、如同文件夹一样包也采用了树形目录的存储方式。同一个包中的类名字是不同的不同的包中的类的名字是可以相同的当同时调用两个不同包中相同类名的类时应该加上包名加以区别。因此包可以避免名字冲突。 3、包也限定了访问权限拥有包访问权限的类才能访问某个包中的类。 Java 使用包package这种机制是为了防止命名冲突访问控制提供搜索和定位类class、接口、枚举enumerations和注释annotation等。 ​ 使用关键字 import 类路径 ​ 什么时候需要使用import导入 ​ 当所需的类和当前类不在一个包路径下时需要使用import导入 ​ 对于Java中的java.lang路径下的类并不需要对其进行导入操作 ​ 在同一个包下所导入的类有多个时那么此时可以使用 * 来替代 ​ 比如import com.shujia.day08.teacher.*; ​ 注意该方式只能导入一层包下的所有类不能进行迭代导入 ​ 当导入的多个类出现重复时(了解) ​ ① 使用非*形式类名称相同会报错 ​ ② 使用*形式直接导入类名称的方式优先级会比*更高 ​ 注意事项 ​ package语句必须是程序的第一条可执行的代码 权限修饰符 在Java中有四种主要的访问修饰符权限修饰符用于控制类、方法和变量的访问级别。这些访问修饰符分别是public、protected、默认package-private默认即不写修饰符和private。下面是这些访问修饰符的作用范围 public 在任何地方都可以访问即对所有类可见。示例类、方法、变量被声明为 public。 protected 同一类中可以访问。同一包中的子类可以访问。不同包中的子类可以访问前提是子类引用的对象是子类的实例。示例方法、变量被声明为 protected。 默认package-private默认即不写修饰符 同一类中可以访问。同一包中的子类可以访问。示例类、方法、变量未使用任何修饰符默认为包内可见。 private 同一类中可以访问。示例方法、变量被声明为 private。 内部类 分类成员内部类、局部内部类、静态内部类、匿名内部类 注意 (1)、内部类仍然是一个独立的类在编译之后内部类会被编译成独立的.class文件但是前面冠以外部类的类名和$符号 。 (2)、内部类不能用普通的方式访问。 (3)、内部类声明成静态的就不能随便的访问外部类的成员变量了此时内部类只能访问外部类的静态成员变量 。 (4)、外部类不能直接访问内部类的的成员但可以通过内部类对象来访问 成员内部类 即在一个类中直接定义的内部类成员内部类与普通类的成员没什么区别可以与普通成员一样进行修饰和限制。成员内部类不能含有static的变量和方法。 package com.test.demo10;public class Outer {private static int number 100;private int j 20;private String name java;public static void outer_funOne(){System.out.println(外部类的静态方法);}public void outer_funTwo(){System.out.println(外部类的普通方法);}//内部类class Demo{//static int demos22;//内部类不能定义静态变量int j 50;//内部类和外部类的实例变量可以共存//成员内部类的方法定义public void demo_funOne(){//内部类中访问内部类自己的变量可以直接使用变量名也可以用this.jSystem.out.println(j);//内部类中访问外部类的成员变量语法外部类类名.this.变量名System.out.println(内部类访问外部类变量Outer.this.j);//如果内部类中没有与外部类中相同的变量也可以直接使用变量名System.out.println(name);//内部类调用外部类方法outer_funOne();//静态方法outer_funTwo();//非静态方法}}public static void outer_funThree(){//外部类静态方法访问成员内部类//先建立外部类对象Outer out new Outer();//根据外部类建立内部类对象Demo demo out.new Demo();//访问内部类方法demo.demo_funOne();//访问内部类成员System.out.println(内部类的成员demo.j);}//外部类成员方法访问成员内部类public void outer_funFirst(){Demo outs new Outer().new Demo();outs.demo_funOne();System.out.println(outs.j);}public static void main(String[] args) {//调用内部类的方法Outer.Demo demo1 new Outer().new Demo();demo1.demo_funOne();System.out.println(demo1.j);Outer out new Outer();System.out.println(out.j);out.outer_funFirst();Outer.outer_funThree();//静态方法用类名直接调用} }局部内部类 在方法中定义的内部类称为局部内部类。与局部变量类似局部内部类不能有访问说明符因为它不是外围类的一部分但是它可以访问当前代码块内的常量和此外围类所有的成员。 需要注意的是 (1)、局部内部类只能在定义该内部类的方法内实例化不可以在此方法外对其实例化。 (2)、局部内部类对象不能使用该内部类所在方法的非final局部变量。 package com.test.demo10;public class Outers {private static int number 100;private int j 20;private String name java;//定义外部类方法public void outer_funOne(int k){final int number 100;int j 50;//方法内部的类局部内部类class Demo{public Demo(int k){demo_funOne(k);}final int number 300;//可以定义与外部类同名的变量//static int j 10;//不可以定义静态变量//内部类方法public void demo_funOne(int k){System.out.println(内部类方法demo_funOne);//访问外部类的变量如果没有与内部类同名的变量可以直接用变量名System.out.println(name);//访问外部类与内部类同名的变量内部与外部都能访问System.out.println(我是内部的this.number);System.out.println(我是外部的Outers.number);System.out.println(内部类方法传入的参数是k);}}Demo demo new Demo(k);//外部类要创建内部类}public static void main(String[] args) {//访问内部类必须要先有外部类对象Outers out new Outers();out.outer_funOne(15);} } 静态内部类嵌套类 如果你不需要内部类对象与其外围类对象之间有联系那你可以将内部类声明为static。这通常称为嵌套类nested class。想要理解static应用于内部类时的含义你就必须记住普通的内部类对象隐含地保存了一个引用指向创建它的外围类对象。然而当内部类是static的时就不是这样了。嵌套类意味着 1. 要创建嵌套类的对象并不需要其外围类的对象。 2. 不能从嵌套类的对象中访问非静态的外围类对象。package com.test.demo10;public class Outer1 {private static int number 100;private int j 20;private String namejava;public static void outer1_funOne(){System.out.println(外部类静态方法outer_funOne);}public void outer1_funTwo(){System.out.println(外部类普通方法);}//静态内部类可以用publicprotectedprivate修饰private static class Demo{static int j 100;//静态内部类可以定义静态和非静态的变量String name C;//静态内部类的静态方法static void demo_funOne(){//静态内部类只能访问外部类的静态成员静态变量、静态方法System.out.println(静态内部类访问外部类静态变量number);outer1_funOne();//访问外部类静态方法}//静态内部类非静态方法void demo_funTwo(){}}public void outer_funThree(){//外部类访问内部类静态成员System.out.println(Demo.j);//访问静态方法Demo.demo_funOne();//访问静态内部类的非静态成员和方法需要实例化内部类Demo demonew Demo();System.out.println(demo.name);demo.demo_funTwo();}public static void main(String[] args) {new Outer1().outer_funThree();} } 匿名内部类★★★ 简单地说匿名内部类就是没有名字的内部类。什么情况下需要使用匿名内部类如果满足下面的一些条件使用匿名内部类是比较合适的 1、只用到类的一个实例。 2、类在定义后马上用到。 3、类非常小推荐是在4行代码以下 4、给类命名并不会导致你的代码更容易被理解。 在使用匿名内部类时要记住以下几个原则 1、 匿名内部类不能有构造方法。 2、 匿名内部类不能定义任何静态成员、方法和类。 3、 匿名内部类不能是public,protected,private,static。 4、 只能创建匿名内部类的一个实例。 5、 一个匿名内部类一定是在new的后面用其隐含实现一个接口或实现一个类。 6、 因匿名内部类为局部内部类所以局部内部类的所有限制都对其生效。 package com.test.demo10;public class HelloWorldAnonymousClasses {//包含两个方法的HelloWorld接口interface HelloWorld{public void greet();public void greetSomeone(String someone);}public void sayHello(){//1.局部类EnglishGreeting实现了HelloWorld接口class EnglishGreeting implements HelloWorld{String nameworld;Overridepublic void greet() {greetSomeone(world);}Overridepublic void greetSomeone(String someone) {name someone;System.out.println(Hello name someone);}}HelloWorld englishGreetingnew EnglishGreeting();//2.匿名类实现接口HelloWorld frenchGreeting new HelloWorld() {String name mundo;Overridepublic void greet() {greetSomeone(tout is monde);}Overridepublic void greetSomeone(String someone) {name someone;System.out.println( 1name);}};englishGreeting.greet();frenchGreeting.greetSomeone(Fred);frenchGreeting.greet();}public static void main(String[] args) {HelloWorldAnonymousClasses myappnew HelloWorldAnonymousClasses();myapp.sayHello();}}该例中用局部类来初始化变量englishGreeting用匿类来初始化变量frenchGreeting和spanishGreeting两种实现之间有明显的区别1局部类EnglishGreetin继承HelloWorld接口有自己的类名定义完成之后需要再用new关键字实例化才可以使用2frenchGreeting、spanishGreeting在定义的时候就实例化了定义完了就可以直接使用3匿名类是一个表达式因此在定义的最后用分号;结束。匿名内部类的语法 如上文所述匿名类是一个表达式匿名类的语法就类似于调用一个类的构建函数new HelloWorld()除些之外还包含了一个代码块在代码块中完成类的定义见以下两个实例 案例一实现接口的匿名类 HelloWorld frenchGreeting new HelloWorld() {String name tout le monde;public void greet() {greetSomeone(tout le monde);}public void greetSomeone(String someone) {name someone;System.out.println(Salut name);}};案例二匿名子类继承父类 package com.test.demo10;public class AnimalTest {private final String ANIMAL 动物;public void accessTest() {System.out.println(匿名内部类访问其外部类方法);}class Animal {private String name;public Animal(String name) {this.name name;}public void printAnimalName() {System.out.println(bird.name);}}// 鸟类匿名子类继承自Animal类可以覆写父类方法Animal bird new Animal(布谷鸟) {Overridepublic void printAnimalName() {accessTest(); // 访问外部类成员System.out.println(ANIMAL); // 访问外部类final修饰的变量super.printAnimalName();}};public void print() {bird.printAnimalName();}public static void main(String[] args) {AnimalTest animalTest new AnimalTest();animalTest.print();} }从以上两个实例中可知匿名类表达式包含以下内部分 操作符new 一个要实现的接口或要继承的类案例一中的匿名类实现了HellowWorld接口案例二中的匿名内部类继承了Animal父类 一对括号如果是匿名子类与实例化普通类的语法类似如果有构造参数要带上构造参数如果是实现一个接口只需要一对空括号即可 一段被{}括起来类声明主体 末尾的;号因为匿名类的声明是一个表达式是语句的一部分因此要以分号结尾 访问作用域内的局部变量、定义和访问匿名内部类成员 匿名内部类与局部类对作用域内的变量拥有相同的的访问权限。 (1)、匿名内部类可以访问外部内的所有成员 (2)、匿名内部类不能访问外部类未加final修饰的变量注意JDK1.8即使没有用final修饰也可以访问 (3)、属性屏蔽与内嵌类相同匿名内部类定义的类型如变量会屏蔽其作用域范围内的其他同名类型变量 (4)、匿名内部类中不能定义静态属性、方法 (5)、匿名内部类可以有常量属性final修饰的属性 (6)、匿名内部内中可以定义属性如上面代码中的代码:private int x 1; (7)、匿名内部内中可以可以有额外的方法父接口、类中没有的方法; (8)、匿名内部内中可以定义内部类 (9)、匿名内部内中可以对其他类进行实例化。 案例一内嵌类的属性屏蔽1 public class ShadowTest {2 3 public int x 0;4 5 class FirstLevel {6 7 public int x 1;8 9 void methodInFirstLevel(int x) { 10 System.out.println(x x); 11 System.out.println(this.x this.x); 12 System.out.println(ShadowTest.this.x ShadowTest.this.x); 13 } 14 } 15 16 public static void main(String... args) { 17 ShadowTest st new ShadowTest(); 18 ShadowTest.FirstLevel fl st.new FirstLevel(); 19 fl.methodInFirstLevel(23); 20 } 21 } 复制代码 输出结果为x 23 this.x 1 ShadowTest.this.x 0 这个实例中有三个变量x1、ShadowTest类的成员变量2、内部类FirstLevel的成员变量3、内部类方法methodInFirstLevel的参数。methodInFirstLevel的参数x屏蔽了内部类FirstLevel的成员变量因此在该方法内部使用x时实际上是使用的是参数x可以使用this关键字来指定引用是成员变量x1 System.out.println(this.x this.x); 利用类名来引用其成员变量拥有最高的优先级不会被其他同名变量屏蔽如1 System.out.println(ShadowTest.this.x ShadowTest.this.x); 案例二匿名内部类的属性屏蔽1 public class ShadowTest {2 public int x 0;3 4 interface FirstLevel {5 void methodInFirstLevel(int x);6 }7 8 FirstLevel firstLevel new FirstLevel() {9 10 public int x 1; 11 12 Override 13 public void methodInFirstLevel(int x) { 14 System.out.println(x x); 15 System.out.println(this.x this.x); 16 System.out.println(ShadowTest.this.x ShadowTest.this.x); 17 } 18 }; 19 20 public static void main(String... args) { 21 ShadowTest st new ShadowTest(); 22 ShadowTest.FirstLevel fl st.firstLevel; 23 fl.methodInFirstLevel(23); 24 } 25 } 复制代码 输出结果为x 23 this.x 1 ShadowTest.this.x 0 (4)、匿名内部类中不能定义静态属性、方法  1 public class ShadowTest {2 public int x 0;3 4 interface FirstLevel {5 void methodInFirstLevel(int x);6 }7 8 FirstLevel firstLevel new FirstLevel() {9 10 public int x 1; 11 12 public static String str Hello World; // 编译报错 13 14 public static void aa() { // 编译报错 15 } 16 17 public static final String finalStr Hello World; // 正常 18 19 public void extraMethod() { // 正常 20 // do something 21 } 22 }; 23 } (5)、匿名内部类可以有常量属性final修饰的属性(6)、匿名内部内中可以定义属性如上面代码中的代码:private int x 1;(7)、匿名内部内中可以可以有额外的方法父接口、类中没有的方法;(8)、匿名内部内中可以定义内部类(9)、匿名内部内中可以对其他类进行实例化。 异常 异常概述 异常就是程序在运行过程中出现的一些错误我们通过面向对象的思想把这些错误也用类来描述那么一旦产生一个错误即就是创建了某一个错误的对象这个对象就是我们所说的异常对象。 1IndexOutOfBoundsException ArrayIndexOutOfBoundsException 数组角标越界异常 角标不在数组范围内 StringfIndexOutOfBoundsException 字符串角标越界异常 角标不在字符串范围内 2NullPointerException空指针异常 对null调用其成员。 3ArithmeticException数学运算异常 非法的数学运算。 4ClassCastException类型转换异常 将类进行错误的强制转换。 5NumberFormatException数字格式化异常 将数字字符串进行解析。 6InputMismatchException输入不匹配异常 在输入时输入非法数据。 7ParseException时间解析异常 非法的时间格式。 8StackOverFlowError栈内存溢出异常 函数递归。 9OutOfMemoryError堆内存异常 数组空间开辟过大 程序中对象太多。 Java异常体系 Thorwable类表示可抛出是所有异常和错误的超类两个直接子类为Error和Exception分别表示错误和异常。 Throwable中的方法 getMessage() 获取异常信息返回字符串。 toString() 获取异常类名和异常信息返回字符串。 printStackTrace() 获取异常类名和异常信息以及异常出现在程序中的位置。返回值void。 printStackTrace(PrintStream s) 通常用该方法将异常内容保存在日志文件中以便查阅。 异常分类 Error Error是程序无法处理的错误它是由JVM产生和抛出的比如OutOfMemoryError、ThreadDeath等。这些异常发生时Java虚拟机JVM一般会选择线程终止。 Exception Exception是程序本身可以处理的异常这种异常分两大类运行时异常和非运行时异常。程序中应当尽可能去处理这些异常。 运行时异常 运行时异常都是RuntimeException类及其子类异常如NullPointerException、IndexOutOfBoundsException等这些异常是不检查异常程序中可以选择捕获处理也可以不处理。这些异常一般是由程序逻辑错误引起的程序应该从逻辑角度尽可能避免这类异常的发生。 非运行时异常 非运行时异常是RuntimeException以外的异常类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常如果不处理程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常一般情况下不自定义检查异常。 处理编译时异常的更多知识 声明异常 在 Java 中当前执行的语句必属于某个方法。Java 解释器调用 main 方法开始执行一个程序。每个方法都必须声明它可能抛出的必检异常的类型。这称为声明异常 declaring exception)。只对编译时异常进行声明、告知方法的调用者有异常。     为了在方法中声明一个异常就要在方法头中使用关键字 throws, 如下所示 public void myMethodO throws IOException关键字 throws 表明 myMethod 方法可齙会抛出异常 IOException。如果方法可能会抛出多个异常就可以在关键字 throws 后添加一个用逗号分隔的异常列表 public void myMethodO throws Exceptionl, Exception2,… ExceptionN注意如果方法没有在父类中声明异常那么就不能在子类中对其进行继承来声明异常。 抛出异常 检测到错误的程序可以创建一个合适的异常类型的实例并抛出它这就称为抛出一个异常throwing an exception)。这里有一个例子假如程序发现传递给方法的参数与方法的合约不符例如方法中的参数必须是非负的但是传入的是一个负参数)这个程序就可以创建 IllegalArgumentException 的一个实例并抛出它如下所示 IllegalArgumentException ex new II1egalArgumentException(Wrong Argument); throw ex;或者大多数使用下面的语句 throw new IllegalArgumentException(Wrong Argument);注意IllegalArgumentException 是 Java API 中的一个异常类。通常JavaAPI 中的每个异常类至少有两个构造方法一个无参构造方法和一个带可描述这个异常的 String 参数的构造方法。该参数称为异常消息exceptionmessage), 它可以用 getMessage()获取。     提示声明异常的关楗字是 throws, 抛出异常的关键字是 throw。 捕获异常 现在我们知道了如何声明一个异常以及如何抛出一个异常。当抛出一个异常时可以在try-catch 块中捕获和处理它 try-catch-finally     try语句块中放的是可能出现问题的代码尽量不要把不相关的代码放入到里面否则会出现截断的问题。 try{codeAthrow ...codeB }如果throw这个地方一旦抛出异常 codeB就不会执行了 建议把codeB放到后面。 catch语句块中放的是出现问题并捕获后处理问题的代码code如果问题在try语句块中没有出现 则catch中不会运行。 catch(Exception e) {code }finally语句块中放的是不管问题异常是否产生 都要执行的代码code。 finally{code//关闭资源IO 数据库 网络结尾处理的一些工作 } 在捕获异常中return的执行顺序 try、catch、finally、return执行顺序超详解析针对面试题 有关try、catch、finally和return执行顺序的题目在面试题中可谓是频频出现。总结一下此类问题几种情况。 不管try中是否出现异常finally块中的代码都会执行 当try和catch中有return时finally依然会执行 finally是在return语句执行之后返回之前执行的此时并没有返回运算后的值而是先把要返回的值保存起来不管finally中的代码怎么样返回的值都不会改变仍然是之前保存的值所以如果finally中没有return即使对数据有操作也不会影响返回值即如果finally中没有return函数返回值是在finally执行前就已经确定了 finally中如果包含return那么程序将在这里返回而不是try或catch中的return返回返回值就不是try或catch中保存的返回值了。注 finally修改的基本类型是不影响 返回结果的。传值 修改listmap自定义类等引用类型时是影响返回结果的。传址的对象也是传址的 但是date类型经过测试是不影响的。try{} catch(){}finally{} return; 按程序顺序运行如果try中有异常会执行catch中的代码块有异常与否都会执行finally中的代码最终返回。 try{ return; }catch(){} finally{} return; 1.先执行try块中return 语句包括return语句中的表达式运算但不返回 2.执行finally语句中全部代码 3.最后执行try中return 返回 finally块之后的语句return不执行因为程序在try中已经return。 示例 package com.test.demo11;public class Test {public int add(int a,int b){try {return ab;}catch (Exception e){System.out.println(catch语句块);}finally {System.out.println(finally语句块);}return 0;}public static void main(String[] args) {Test test new Test();System.out.println(和是test.add(9,34));} } 结果 finally语句块 和是43至于为什么不是和是 finally块43的原因 System.out.println(“和是”test.add(9,34)); 这是进行字符串拼接是一个整体所以首先是进入add方法进去之后先不运算result而是输出finally块。finally语句块这句话先打印到控制台中。打印完后返回来执行try中的return得到43此时再将结果与和是拼接输出和是43.所以最终输出finally语句块 和是43。 try{} catch(){return;} finally{} return; 程序先执行try如果遇到异常执行catch块最终都会执行finally中的代码块 有异常 执行catch中的语句和return中的表达式运算但不返回 执行finally语句中全部代码 最后执行catch块中return返回。 finally块后的return语句不再执行。 无异常执行完try再finally再return… 示例 有异常public class Test04 {public static void main(String[] args) {System.out.println(test());}private static int test() {int temp 1;try {System.out.println(temp);int i1/0;} catch (Exception e) {System.out.println(temp);return temp;} finally {temp;System.out.println(temp);}return temp;} }输出1132先执行try中的打印temp1有异常执行catch中的打印然后执行return中的表达式运算此时temp2并将结果保存在临时栈中但不返回执行finally中的语句temp此时temp更新为3同时打印但因为finally中的操作不是return语句所以不会去临时栈中的值此时临时栈中的值仍然是2。finally中的执行完后执行catch中的返回即2。示例2无异常public class Test04 {public static void main(String[] args) {System.out.println(test());}private static int test() {int temp 1;try {System.out.println(temp);} catch (Exception e) {System.out.println(temp);return temp;} finally {temp;System.out.println(temp);}return temp;} }输出123try{ return; }catch(){} finally{return;} 执行try块中的代码和return语句包括return语句中的表达式运算但不返回try中return的表达式运算的结果放在临时栈 再执行finally块 执行finally块和return中的表达式运算并更新临时栈中的值从这里返回。 此时finally块的return值就是代码执行完后的值 try{} catch(){return;}finally{return;} 执行try中的语句块 有无异常 有异常程序执行catch块中return语句包括return语句中的表达式运算,并将结果保存到临时栈但不返回 无异常直接执行下面的 再执行finally块 执行finally块return中的表达式运算并更新临时栈中的值并从这里返回。 示例 无异常public class Test04 {public static void main(String[] args) {System.out.println(test());}private static int test() {int temp 1;try {System.out.println(temp);} catch (Exception e) {System.out.println(temp);return temp;} finally {System.out.println(temp);return temp;}} } 输出112有异常public class Test04 {public static void main(String[] args) {System.out.println(test());}private static int test() {int temp 1;try {System.out.println(temp);int i1/0;} catch (Exception e) {System.out.println(temp);return temp;} finally {System.out.println(temp);return temp;}} }输出1123try{ return;}catch(){return;} finally{return;} 程序执行try块中return语句包括return语句中的表达式运算但不返回 ​ 有异常 ​ 执行catch块中的语句和rreturn语句中的表达式运算但不返回结果保存在临时栈 ​ 再执行finally块 ​ 执行finally块有return更新临时栈的值并从这里返回。 ​ 无异常 ​ 直接执行finally块 ​ 执行finally块有return更新临时栈的值并从这里返回。 示例 无异常 package com.jc;public class Test04 {public static void main(String[] args) {System.out.println(test());}private static int test() {int temp 1;try {System.out.println(temp); // int i1/0;return temp;} catch (Exception e) {System.out.println(temp);return temp;} finally {System.out.println(temp);return temp;}} }输出123有异常 package com.jc;public class Test04 {public static void main(String[] args) {System.out.println(test());}private static int test() {int temp 1;try {System.out.println(temp);int i1/0;return temp;} catch (Exception e) {System.out.println(temp);return temp;} finally {System.out.println(temp);return temp;}} } 输出1123 try{ return;}catch(){return;} finally{其他} 程序执行try块中return语句包括return语句中的表达式运算但不返回 有异常 执行catch块中return语句包括return语句中的表达式运算但不返回 再执行finally块 无异常 再执行finally块 执行finally块有return从这里返回。 示例 public class Test {public static void main(String[] args) {System.out.println(test());}private static int test() {int temp 1;try {System.out.println(temp);return temp;} catch (Exception e) {System.out.println(temp);return temp;} finally {temp;System.out.println(temp);}} } 输出结果为132执行顺序为输出try里面的初始temp1 temp2 保存return里面temp的值2 执行finally的语句temp3输出temp3 返回try中的return语句返回存在里面的temp的值2 输出temp2。 finally代码块在return中间执行。return的值会被放入临时栈然后执行finally代码块如果finally中有return会刷新临时栈的值方法结束返回临时栈中的值。 小结 任何执行try 或者catch中的return语句之后在返回之前如果finally存在的话都会先执行finally语句 如果finally中有return语句那么程序就return了所以finally中的return是一定会被return的 编译器把finally中的return实现为一个warning。 不管有没有异常finally代码块包括finally中return语句中的表达式运算都会在return之前执行 多个return中的表达式运算是按顺序执行的多个return执行了一个之后后面的return就不会执行。不管return是在try、catch、finally还是之外。 泛型 什么是泛型 型即“参数化类型”。我们最熟悉的就是定义方法时有形参然后调用此方法时传递实参。 本质其本质是参数化类型也就是说所操作的数据类型被指定为一个参数type parameter这种参数类型可以用在类、接口和方法的创建中分别称为泛型类、泛型接口、泛型方法。 例如 ArrayListE objectName new ArrayList();  E: 泛型数据类型用于设置 objectName 的数据类型只能为引用数据类型。 作用 **第一是泛化。**可以用T代表任意类型Java语言中引入泛型是一个较大的功能增强不仅语言、类型系统和编译器有了较大的变化以支持泛型而且类库也进行了大翻修所以许多重要的类比如集合框架都已经成为泛型化的了这带来了很多好处。 **第二是类型安全。**泛型的一个主要目标就是提高Java程序的类型安全使用泛型可以使编译器知道变量的类型限制进而可以在更高程度上验证类型假设。如果不用泛型则必须使用强制类型转换而强制类型转换不安全在运行期可能发生ClassCast Exception异常如果使用泛型则会在编译期就能发现该错误。 **第三是消除强制类型转换。**泛型可以消除源代码中的许多强制类型转换这样可以使代码更加可读并减少出错的机会。 **第四是向后兼容。**支持泛型的Java编译器例如JDK1.5中的Javac可以用来编译经过泛型扩充的Java程序Generics Java程序但是现有的没有使用泛型扩充的Java程序仍然可以用这些编译器来编译。 优点 1、类型安全 2、消除强制类型转换 3、更高的运行效率 4、潜在的性能收益 泛型分类 泛型类、泛型接口、泛型方法 首先我们得先了解泛型字母的含义 字母意义E-Element在集合中使用因为集合中存放的是元素T-TypeJava类K - Key键v - Value值N- Number数值类型 泛型类 定义格式 修饰符 class类名代表泛型的变量{} 例子 /*** Description: $定义一个含有泛型的类, 模拟Arraylist集合* 泛型是一个未知的数据类型,当我们不确定什么什么数据类型的时候,可以使用泛型* 泛型可以接牧任意的数据类型,可以使用Integer , String, student.. .* 创建对象的时候确定泛型的数据类型* Author: dyq* Date: $*/ public class GenericClassE {private E name;public E getName() {return name;}public void setName(E name) {this.name name;}public static void main(String[] args) {//不写泛型默认为ObjectGenericClass gc new GenericClass();gc.setName(我是Object);Object name gc.getName();System.out.println(name);//可以通过创建对象时确定数据类型//泛型使用Integer类型GenericClassInteger Igc new GenericClass();Igc.setName(1);Integer i Igc.getName();System.out.println(我是Interger类型i);//泛型使用String类型GenericClassString sgc new GenericClass();sgc.setName(花花);String s sgc.getName();System.out.println(我是String类型s);} }结果 我是Object 我是Interger类型1 我是String类型花花 泛型方法 语法 修饰符泛型返回值类型方法名(参数列表(使用泛型)){ 方法体; } 例子 /*** Description: 泛型方法$ 含有泛型的方法在调用方法的时候确定泛型的数据类型* 传递什么类型的参数泛型是什么类型* Author: dyq* Date: $2021年2月5日*/ public class GenericMethod {//定义一个含有泛型的方法public M void method01(M m){System.out.println(m);}//定义一个含有泛型的静态方法public static S void method02(S s){System.out.println(s);}//测试含有泛型的主方法public static void main(String[] args) {GenericMethod m new GenericMethod();m.method01(10);m.method01(你好);m.method01(男);m.method01(19);System.out.println();m.method02(我是方法02);m.method02(ok!);m.method02(1);m.method02(女);} }结果 10 你好 男 19我是方法02 ok! 1 女 泛型接口 格式 修饰符interface接口名代表泛型的变量{ } 例子 /*** Description: 泛型接口$* Author: dyq* Date: 2021年2月5日$*/ public interface GenericInterfaceE {public abstract void add(E e);public abstract E getE(); } 有两种实现方法先创建一个GenericInterfaceImpl01类 /*** Description: $含有泛型的接口第一种方式定义接口的实现实现接口指定接口的泛型* Author: dyq* Date: $*/ public class GenericInterfaceImpl01 implements GenericInterfaceString{Overridepublic void add(String s) {System.out.println(s);}Overridepublic String getE() {return null;} } 再创建一个GenericInterfaceImpl02实现类 /*** Description: $含有泛型的接口第二种使用方式:接口使用什么泛型,* 实现类就使用什么泛型,类跟着接口走就相当于定义了一个含有泛型的类,* 创建对象的时候确定泛型的类型* Author: dyq* Date: $* public interface ListE{* boolean add(E e);* E get(int index);* }* public class ArrayListE impLements ListE{* }*/ public class GenericInterfaceImpl02I implements GenericInterfaceI {Overridepublic void add(I i) {System.out.println(i);}Overridepublic I getE() {return null;} } 最后新建一个测试类 /*** Description: $测试含有泛型的接口* Author: dyq* Date: $*/ public class GenericInterfaceTest {public static void main(String[] args) {//创建GenericInterfaceImplGenericInterfaceImpl01 gil new GenericInterfaceImpl01();gil.add(哈哈哈~);//创建GenericInterfaceImpl01 定义输出的数据类型GenericInterfaceImpl02Integer gil2 new GenericInterfaceImpl02Integer();gil2.add(10);GenericInterfaceImpl02Double gil3 new GenericInterfaceImpl02Double();gil3.add(8.88);} } 结果: 哈哈哈~ 10 8.88 泛型的通配符 当使用泛型类或者接口时传递的数据中泛型类型不确定可以通过通配符 表示。但是一旦使用泛型的通配符后只能使用Object类中的共性方法集合中元素自身方法无法使用。 通配符基本使用 泛型的通配符:不知道使用什么类型来接收的时候,此时可以使用?,?表示未知通配符。此时只能接受数据,不能往该集合中存储数据。 例子 import java.util.ArrayList; import java.util.Iterator;/*** Description: $类型通配符一般是使用?代替具体的类型参数* Author: dyq* Date: $*/ public class GenericTest {public static void main(String[] args) {ArrayListInteger list new ArrayList();list.add(1);list.add(2);ArrayListString list1 new ArrayList();list1.add(a);list1.add(b);printArray(list);printArray(list1);}/*定义一个方法能遍历所有类型的ArrayList集合* 这时候我们知道ArrList集合使用说明数据可以泛型的通配符来接收数据类型*/public static void printArray(ArrayList? list){//使用迭代器遍历集合Iterator? it list.iterator();while (it.hasNext()){//it.next()方法。取出的元素是object可以接收任意的数据类型Object o it.next();System.out.println(o);}} }结果 1 2 a b 类型通配符上限通过形如List来定义如此定义就是通配符泛型值接受Number及其下层子类类型。 类型通配符下限通过形如 List? super Number来定义表示类型只能接受Number及其三层父类类型如 Object 类型的实例。 import java.util.ArrayList; import java.util.Collection;/*** Description: $泛型的上线限定 extends E 代表我使用的泛型只能是E类型/本身* 泛型的下限定 super E 代表我使用的泛型只能是E类型/本身* Author: dyq* Date: $*/ public class GenericTest01 {public static void main(String[] args) {CollectionInteger list1 new ArrayListInteger();CollectionString list2 new ArrayListString();CollectionNumber list3 new ArrayListNumber();CollectionObject list4 new ArrayListObject();getElement1(list1);getElement1(list2); //报错getElement1(list3);getElement1(list4);//报错getElement2(list1);//报错getElement2(list2);//报错getElement2(list3);getElement2(list4);/*类与类之间的继承关系Integer extends Number extents ObjectSTring extends Object* */}//泛型的上限:此时的泛型必须是Number类型或者Number类型的子类public static void getElement1(Collection? extends Number coll){}//泛型的下限:此时的泛型必须是Number类型或者Number类型的父类public static void getElement2(Collection? super Number collection){} }结果自动装箱和自动拆箱 支持自动装箱的基本数据类型和其对应的包装类有byte - Byte short - Short int - Integer long - Long float - Float double - Double char - Character boolean - Boolean 这些基本数据类型都有其对应的包装类因此可以进行自动装箱和拆箱 对于其他类型如自定义的类或其他基本数据类型是不支持自动装箱和拆箱的。如果需要将其转换需要手动进行装箱和拆箱操作。对于基本数据类型由于其并不是一个类所以无法构建其对象通过操作对象的方法完成相关操作于是 Java提供对于基本数据类型的包装类int Integer基本数据类型和包装类Byte,Short,Integer,Long,Float,Double,Character,Booleanbyte,short,int,long,float,double,char,boolean对于包装类存在由 自动装箱和自动拆箱操作自动拆箱:对于包装类对象可以直接将其赋予给对应的基本数据类型比如Integer i2 Integer.valueOf(str);int i3 i2;int i4 Integer.valueOf(str);自动装箱:当所需要的类型是包装类但此时可以使用对应的基本数据类型来传递注意对于包装类也可以使用 运算符 来完成相关操作对于自定义的类或其他引用类型Java 中并没有像基本数据类型和其对应的包装类那样提供自动装箱和自动拆箱的特性。自动装箱和拆箱仅适用于基本数据类型和其包装类之间的转换。如果需要在自定义类或其他引用类型之间进行转换需要手动进行装箱和拆箱的操作。通常这包括通过构造方法或者提供特定的方法来进行转换。举个例子假设有一个自定义的类 MyClasspublic class MyClass {private int value;public MyClass(int value) {this.value value;}public int getValue() {return value;} } 手动进行装箱和拆箱的示例// 手动装箱 int intValue 42; MyClass myObject new MyClass(intValue);// 手动拆箱 int retrievedValue myObject.getValue(); 在这个例子中我们使用 new MyClass(intValue) 进行手动装箱将基本数据类型的值封装到 MyClass 对象中。然后通过调用 getValue() 方法进行手动拆箱获取封装在对象中的值。Collection list2 new ArrayList(); Collection list3 new ArrayList(); Collection list4 new ArrayList(); getElement1(list1);getElement1(list2); //报错getElement1(list3);getElement1(list4);//报错getElement2(list1);//报错getElement2(list2);//报错getElement2(list3);getElement2(list4);/*类与类之间的继承关系Integer extends Number extents ObjectSTring extends Object* */ } //泛型的上限:此时的泛型必须是Number类型或者Number类型的子类 public static void getElement1(Collection? extends Number coll){ } //泛型的下限:此时的泛型必须是Number类型或者Number类型的父类 public static void getElement2(Collection? super Number collection){}} 结果 ## 自动装箱和自动拆箱 支持自动装箱的基本数据类型和其对应的包装类有 byte - Byte short - Short int - Integer long - Long float - Float double - Double char - Character boolean - Boolean 这些基本数据类型都有其对应的包装类因此可以进行自动装箱和拆箱 对于其他类型如自定义的类或其他基本数据类型是不支持自动装箱和拆箱的。如果需要将其转换需要手动进行装箱和拆箱操作。 对于基本数据类型由于其并不是一个类所以无法构建其对象通过操作对象的方法完成相关操作 于是 Java提供对于基本数据类型的包装类 int Integer 基本数据类型和包装类Byte,Short,Integer,Long,Float,Double,Character,Booleanbyte,short,int,long,float,double,char,boolean对于包装类存在由 自动装箱和自动拆箱操作自动拆箱:对于包装类对象可以直接将其赋予给对应的基本数据类型比如Integer i2 Integer.valueOf(str);int i3 i2;int i4 Integer.valueOf(str);自动装箱:当所需要的类型是包装类但此时可以使用对应的基本数据类型来传递注意对于包装类也可以使用 运算符 来完成相关操作对于自定义的类或其他引用类型Java 中并没有像基本数据类型和其对应的包装类那样提供自动装箱和自动拆箱的特性。自动装箱和拆箱仅适用于基本数据类型和其包装类之间的转换。 如果需要在自定义类或其他引用类型之间进行转换需要手动进行装箱和拆箱的操作。通常这包括通过构造方法或者提供特定的方法来进行转换。 举个例子假设有一个自定义的类 MyClass public class MyClass { private int value; public MyClass(int value) {this.value value; }public int getValue() {return value; }} 手动进行装箱和拆箱的示例 // 手动装箱 int intValue 42; MyClass myObject new MyClass(intValue); // 手动拆箱 int retrievedValue myObject.getValue(); 在这个例子中我们使用 new MyClass(intValue) 进行手动装箱将基本数据类型的值封装到 MyClass 对象中。然后通过调用 getValue() 方法进行手动拆箱获取封装在对象中的值。
http://www.dnsts.com.cn/news/223887.html

相关文章:

  • 评网网站建设自己做国际网站
  • 申请网站怎么申请ai中如何做网站切图
  • 青岛制作网站的wordpress网站内容
  • 惠阳市网站建设定制型网站建设推广
  • 公司网站用什么系统平江做网站的公司
  • 团购网站模板编辑首页网店如何引流与推广
  • 网络营销师怎么考企业网站seo成功案例
  • 网站开发和软件开发哪个好wordpress放哪
  • 博兴网站建设合肥建设云app
  • 学院网站建设时间控制变更申请表网站上传后后台进不去
  • 找设计方案的网站高端网站建设公司哪家更专业
  • 中小企业网站营销型网站要点
  • 医疗网站建设资讯动态表白网站制作
  • 个人网站名称怎么起大连住房和城乡建设官网
  • 淄博网站的优化岳阳网站设计公司
  • 大网站成本装企营销网站建设
  • 江苏省网站建设哪家好商丘有哪些大型企业
  • 设计师找图网站wordpress导航栏下拉菜单代码
  • ppt模板网站排行榜公司门户网站是什么
  • 专门做lolh的网站免费做网络推广
  • dw是做静态网站还是动态的网络程序设计实验报告
  • 做视频网站需要什么条件WordPress文章批量生成器
  • 网站建设 检查 通报2345浏览器网址
  • 郑州网站建设报价微信企业邮箱
  • 安徽合肥网站制作纸业建站服务
  • 淘宝客怎么做推广网站英文网站建设公司
  • 广州南沙建设和交通局网站厦门app制作
  • 网站开发的背景如何在对方网站上做外链
  • vue适合什么网站开发新手做网站做什么样的
  • 手机响应式网站wordpress摘要插件