Java基础整理03
Exercise
Test 03
面向对象
本质:以类的方法组织代码,以对象的组织封装数据
三大特征:封装、继承、多态
类与对象
静态方法:和类一起加载的,一个静态方法只能调用静态的东西
非静态方法:类实例化之后才存在
方法中的实参和形参的类型要一一对应
类名 对象名称 = new 类名(); //类被实例化后才可使用,称为对象
对象名称.属性名 //使用对象访问类中的属性
对象名称.方法名() // 访问类中的方法
//首先写一个包含属性和方法的类
public class Student{
//属性:字段Field(成员变量)
String name;
int age;
//方法
public void study(){
System.out.println(this.name+"2001");
}
}
//main中调用后类被实例化成对象
public class Application{
public static void main(String[] args){
Student jc = new Student(); //创建对象
jc.name = "久诚";
jc.age = 22;
System.out.println(jc.name); //久诚
System.out.println(jc.age); //22
}
}
使用new关键字创建对象时,除了分配内存空间以外,还会给创建好的对象进行默认初始化,以及对类中构造器的调用。
构造方法
构造器即构造方法是在进行创建对象时必须调用的。
特点:1、构造方法没有返回值(不能写void)
2、构造方法名称必须和类名相同
3、构造方法主要是完成方法对属性的初始化工作
public class Person{
String name;
public Preson(){ //无参定义(与下面的有参构造方法互为重载)
}
public Person(String name){ //有参,一但定义了有参构造,无参就必须显示定义
this.name = name; //当使用构造方法赋值时,使用this调用本类的成员属性
}
}
public class Application{
public static void main(String[] args){
Person person = new Person("清清"); //使用new关键字,本质是调用构造器
System.out.println(person.name); //清清
}
}
注:如果不定义构造方法,那么Jvm会自动为该类生成一个无参构造方法
如果定义了有参构造方法,Jvm将不再生成无参构造方法
如果想使用无参构造,显示的定义一个无参构造
创建对象内存分析(了解)
public class Pet{
public String name;
public int age;
public void shout(){
System.out.println)("叫");
}
}
public class Application{
public static void main(String[] args){
Pet dog = new Pet();
dog.name = "小狗";
dog.age = 3;
dog.shout();
System.out.println(dog.name);
System.out.println(dog.age);
Pet cat = new Pet();
}
}

小结1
数据类型分为基本数据类型和引用数据类型
基本数据类型(8种): 整型:byte(8位1字节)、short(16位2字节)、int(32位4字节)、long(64位8字节)
浮点型:float(32位4字节)、double(64位8字节)
布尔类型:boolean(8位1字节):true、false
字符类型:char(16位2字节)
低 ---------------------------------------------------> 高
byte、short、char -> int -> long -> float -> double
转换顺序: 低容量到高容量是自动转换:byte、short、char 自动转换成 int、long、float、double
高容量到低容量是强制转换:
运算类型:如果两个操作数中有一个是double类型,那么自动转换成double类型
如果两个操作数中有一个是float类型,那么自动转换成float类型
如果两个操作数中有一个是long类型,那么自动转换成long类型
除此之外,都自动转换成int类型(如果两个short进行运算,也要先转换成int类型)
引用数据类型:类、接口、数组
对象是通过引用来操作的:栈 ----> 堆
封装
private:私有(出了这个类之外不能直接访问到)
如果属性可以封装和不封装时,优先选择封装,如果方法也可选,优先选择不封装。
private 属性类型 属性名称; //属性封装
private 方法返回值 方法名称(参数){}; //方法封装
public class Student{
//属性私有
private String name;
private int id;
private char sex;
//提供一些public的get和set方法操作该私有属性
public String getName(){ //get:获得这个数据
return this.name;
}
public void setName(String name){ //set:给这个数据设置值(set方法里可以写一些安全性判断,校验合不合理)
this.name = name;
}
}
public class Application{
public static void main(String[] args){
Student s1 = new Student();
s1.setName("清清");
System.out.println(s1.getName()); //清清
}
}
继承(单继承、多实现)
extends:扩展(子类对父类的扩展)
在Java中,所有的类都默认直接或间接继承Object类。
当创建子类对象的时候,首先会创建父类对象(调用父类的构造方法),
然后才是创建子类对象(调用子类的构造方法)。
class 父类{} //定义父类
class 子类 extends 父类{} //使用extends关键字实现继承
public class Person{
private int money = 10_0000; //子类不能继承父类私有的东西,但可以调用父类中的非私有方法来访问私有属性(例如set和get方法)
public int age = 21;
public void say(){
System .out.println("清清");
}
}
public class Student extends Person{ //子类继承了父类中的全部方法
}
public class Application{
public static void main(String[] args){
Student student = new Student();
student.say();
System.out.println(student.age); /*清清
21*/
//System.out.println(student.money); //报错,money是父类的私有属性
}
}
注:子类不能继承父类的构造方法和私有的东西。
super关键字:super调用父类普通方法、 调用父类属性、 调用父类构造方法(必须在构造方法的第一个)
super必须只能出现在子类的方法或者构造方法中
super和this不能同时调用构造方法
super和this关键字区别:

5 前提 没有继承也可以使用 只能在继承条件才可使用
public class Person{
protected String name = "清清";
public void print(){
System.out.println("Person");
}
}
public class Student extends Person{
private String name = "花海";
public void print(){
System.out.println("Student");
}
public void test(String name){
System.out.println(name); //传参
System.out.println(this.name); //本类
System.out.println(super.name); //调用父类属性
}
public void tes1(){
print();
this.print();
super.print(); //调用父类普通方法
}
}
public class Application{
public static void main(String[] args){
Student student = new Student();
student.test("久诚");
student.test1();
}
}

public class Person{
public Person(){
System.out.println("父类无参");
}
}
public class Student extends Person{
public Student(){
//隐藏代码,调用父类的无参构造方法
super(); //调用父类的构造器,必须要在子类构造器的第一行
System.out.println("子类无参");
}
}
public class Application{
public static void main(String[] args){
Student student = new Student();
}
}

方法的重写:
子类中定义了与父类中重名的方法,称之为方法的重写。
public class B {
public static void test(){
System.out.println("B中的test");
}
}
public class A extends B {
public static void test(){
System.out.println("A中的test");
}
}
public class Application {
public static void main(String[] args) {
A a = new A();
a.test(); //静态绑定:方法的调用只和等号左边定义的数据类型有关
B b = new B(); //父类的引用指向子类的对象(向上转型)
b.test();
}
}

b是A new出来的对象,因此调用了A的方法,因为静态方法是类的方法,而非静态是对象的方法,没有static时,b调用的是对象的方法。
public class B {
public void test(){
System.out.println("B中的test");
}
}
public class A extends B {
@Override//重写
public void test(){
System.out.println("重写B的test");
}
}
public class Application {
public static void main(String[] args) {
A a = new A();
a.test();
B b = new B(); //子类重写了父类的方法
b.test();
}
}

注:需要有继承关系,子类重写父类的方法时,
1)方法名、参数列表、返回值类型必须相同,方法体不同。
2)访问权限不能缩小(public > Protected > Default > private)
3)父类中的方法不能是私有访问。
4)抛出异常的范围可以被缩小,但不能扩大。(ClassNotFoundExpection < Expection)
多态
即同一方法可以根据发送对象的不同而采用多种不同的行为方式。
父类 父类对象 = 子类实例; //向上转型(自动)父类引用指向子类对象
子类 子类对象 = (子类)父类实例; //向下转型(强制)
instanceof关键字 (类型转换) 引用类型,判断一个对象是什么类型(两个类是否存在父子关系)
对象 instanceof 类;
public class A {
public void fun1(){
System.out.println("父类---fun1()");
}
public void fun2(){
System.out.println("父类---fun2()");
}
}
public class B extends A {
public void fun1(){ //子类重写父类方法
System.out.println("子类B--fun1()");
}
public void fun3(){
System.out.println("子类B--fun3()");
}
}
public class C extends A {
public void fun1(){
System.out.println("子类C--fun1()");
}
public void fun5(){
System.out.println("子类C--fun5()");
}
}
public class Test1 {
public static void main(String[] args) {
/* B b = (new B()); //实例化子类对象
A a = b; //向上转型
a.fun1(); //此方法被子类B覆写(多态:表面上看调用的是父类对象,实际运行是子类方法)*/
fun(new B()); //传递B的实例
fun(new C());
}
public static void fun(A a){ //直接用父类对象接收所有子类里的a.fun1()方法和a.fun2()方法,向上转型只能调用父类和子类都有的方法
a.fun1(); //子类覆写
a.fun2(); //子类继承
if(a instanceof B) {
B b = (B) a; //向下转型
b.fun3();
}else if(a instanceof C){
C c = (C) a;
c.fun5();
}
}
}

注:1、多态是方法的多态,属性没有多态。
2、父类要和子类有联系,否则会发生类型转换异常:ClassCastException
3、存在条件:继承关系,方法需要重写
不能重写:1)static方法。属于类,不属于实例
2)final常量
3)private私有方法
final关键字:(完结器)
使用final定义类,不能被继承(不能有子类),也就不能被重写。
final声明属性并赋值,不能被修改。
final不能修饰构造方法。
static关键字:
1、static属性
static 属性类型 属性名称; //全局属性(静态属性、类属性)
static final 常量名 = 值; //静态常量
static final double PI = 3.14;
2、static方法:静态方法不允许被覆盖,只能重新定义
public static 返回值类型(参数列表){} //全局方法(静态方法、类方法)
3、代码块
public class Demo01 {
{ //赋初值
System.out.println("匿名代码块");
}
static { //只执行一次
System.out.println("静态代码块");
}
public Demo01(){
System.out.println("构造器");
}
public static void main(String[] args) {
Demo01 d1 = new Demo01();
System.out.println("----------------------");
Demo01 d2 = new Demo01();
}
}

小结2:
访问控制修饰符:
public:类的声明、成员属性、成员方法、不能修饰本地属性
private:不能类的声明、成员属性、成员方法、不能修饰本地属性、继承不到
default:类的声明、成员属性、成员方法
protected:不能类的声明、成员属性、成员方法、继承
只有public和default可以放到class前面
非访问控制修饰符:
static关键字:不能放在类的声明部分、成员属性、成员方法
final关键字:能放在类的声明部分(除抽象类)、成员属性、成员方法、有时可以和static连用
this关键字:表明当前对象(成员属性)、调用本类中其他构造方法
抽象(单继承)(存在约束)
abstract关键字:声明抽象类和抽象方法
abstract class 抽象类名称{
属性;
访问权限 返回值类型 方法名称(参数){
[return 返回值]
}
//抽象方法
访问权限 abstract 返回值类型 方法名称(参数);
//抽象方法中没有方法体!(抽象类至少包含一个抽象方法,抽象方法只需声明不能实现,所以也不能用static修饰)
}
抽象类不能被实例化,只能通过子类重写去实现抽象方法
抽象方法必须存在于抽象类中,但抽象类里可以有普通方法,可以定义无参构造器
public abstract class A {
public static final String FLAG = "fmvp";
private String name = "花海";
public String getName(){
return name;
}
private void setName(String name){
this.name = name;
}
public abstract void print(); //抽象方法
}
public class B extends A {
@Override //方法重写
public void print() {
System.out.println("FLAG:" + FLAG);
System.out.println("姓名:" + getName());
}
}
public class Test {
public static void main(String[] args) {
B b = new B();
b.print();
}
}
接口(多继承)(约束和实现分离)
interface关键字:接口的定义
[修饰符] interface 接口名称{
全局常量;
抽象方法
}
implements关键字:接口的实现
class 子类 implements 接口A,接口B,...{} //接口的实现
接口中的所有定义的方法都是抽象的(public abstract),所以接口都需要一个实现类来重写接口中的方法
定义的属性都是全局静态常量(public static final)(不常用)
public interface A {
String AUTHOR = "清清"; //全局常量
void print();
String getInfo();
}
public interface B {
void say();
}
public class X implements A, B {
@Override
public void say() {
System.out.println("apple");
}
@Override
public void print() {
System.out.println("作者:" + AUTHOR);
}
public String getInfo() {
return "aaa";
}
}
public class Test {
public static void main(String[] args) {
X x = new X();
x.say();
x.print();
System.out.println(x.getInfo());
}
}
N种内部类
在一个类的内部再定义一个类。特点:①编译之后可生成独立的字节码文件:Outer$Inner.class
②内部类可直接访问外部类的私有成员而不破坏封装
③可为外部类提供必要的内部功能组件
成员内部类:内部类能操作外部类的私有属性,成员内部类不能定义静态成员,但可包含静态常量。
public class Outer {
private int id = 10;
private String name = "久诚";
public void out(){
System.out.println("外部类的方法");
}
//成员内部类
public class Inner{
private String name = "花海";
private static final String city = "山东"; //静态常量
public void in(){
System.out.println("内部类方法");
System.out.println(name); //当内部类、外部类存在重名属性时,优先访问内部类属性
System.out.println(Outer.this.name); //打印外部类属性
}
public void getID(){ //获得外部类的私有属性
System.out.println(id);
}
}
}
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner(); //通过外部类实例化内部类
inner.in();
inner.getID();
}
}
静态内部类:不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员。
public class Outer {
private int age = 10;
private String name = "清清";
public void out(){
System.out.println("外部类的方法");
}
//静态内部类,和外部类级别相同
static class Inner{
private String address = "111";
private static int id = 10;
public void show(){
Outer outer = new Outer(); //调用外部类对象属性
System.out.println(outer.name);
System.out.println(address); //调用静态内部类的属性和方法
System.out.println(Inner.id); //调用静态内部类的静态属性
}
}
}
public class Application {
public static void main(String[] args) {
Outer.Inner inner = new Outer.Inner();
inner.show();
}
}

局部内部类:定义在外部类的方法中,作用范围和创建对象范围仅限于当前方法。
内部类可以访问static,但是static修饰的内部类不能直接访问外部非静态属性。
public class Outer {
public void method(){
//局部内部类,不能加任何访问修饰符
final String name = "花海"; //无法保证变量的生命周期与自身相同,变量必须修饰final(jdk1.8后会自动加final变成常量)
class Inner{
private String phone = "111222333";
public void in(){
System.out.println(name); //访问局部变量,变量必须是常量(jdk1.7要求)
System.out.println(phone);
}
}
Inner inner = new Inner(); //创建局部内部类对象
inner.in();
}
}
public class Application {
public static void main(String[] args) {
Outer.outer = new Outer();
inner.in();
}
}
匿名内部类:没有类名的局部内部类(特征与局部内部类相同),必须继承一个父类或者实现一个接口
一个java类中可以有多个class类,但只能有一个public class
public class Demo02 {
public static void main(String[] args) {
new Apple().eat(); //没有名字初始化类,不用将实例保存到变量中
Pat pat = new Pat(){
@Override
public void hello() {
}
};
}
}
class Apple{
public void eat(){
System.out.println("1");
}
}
interface Pat{
void hello();
}
异常
异常指程序运行中出现的不期而至的各种状况,如文件找不到、网络连接失败、非法参数等。
异常发生在程序运行期间,它影响了正常的程序执行流程。
public class Demo03 {
public static void main(String[] args) {
System.out.println(11/0);
}
}

Error和Expection
Java把异常当做对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。
Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception。

Error:
Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。
Java虚拟机运行错误(Virtual MachineError),当JVM不再有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发
生时,JVM一般会选择线程终止。
在虚拟机试图执行应用时,如类定义错误(NoClassDefDoundError)、链接错误(LinkageError)。这些错误是不可查的,因为它们在应
用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。
Expection:
在Exception分支有一个重要的子类RuntimeExpection(运行时异常)
ArrayIndexOutOfBoundsException(数组下标越界)
NullPointerException(空指针异常)
ArithmeticException(算数异常)
MissingResourceException(丢失资源)
ClassNotFoundException(找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。
这些异常一般是由程序逻辑错误引起的,程序应该尽可能避免这类异常发生。
捕获和抛出异常
关键字:try、catch、finally、throw、throws
捕获异常:
public class Demo03 {
public static void main(String[] args) {
int a = 1;
int b = 0;
try { //try监控区域
System.out.println(a/b);
} catch (Error e) { //catch(想要捕获的异常类型)捕获异常
System.out.println("Error");
} catch (Exception e){
System.out.println("Exception");
e.printStackTrace(); //打印错误的栈信息
} catch (Throwable t){
System.out.println("Throwable");
} finally { //处理善后
System.out.println("finally");
}
}
}

注:假设要捕获多个异常,范围要从小到大,因为他只匹配一次。
抛出异常:
public class Demo03 {
public static void main(String[] args) {
new Demo03().test(1,0);
}
public void test(int a,int b){
if (b == 0){
throw new ArithmeticException(); //主动抛出异常,一般在方法中使用
}
System.out.println(a/b);
}
}

public class Demo03 {
public static void main(String[] args) {
try {
new Demo03().test(1,0);
} catch (ArithmeticException e) {
e.printStackTrace();
}
}
public void test(int a,int b) throws ArithmeticException{ //假设方法中处理不了异常,则在方法上抛出异常
if (b == 0){
throw new ArithmeticException();
}
System.out.println(a/b);
}
}
自定义异常
public class MyException extends Exception {
//传递数字>10
private int detail;
public MyException(int a) {
this.detail = a;
}
@Override
public String toString() { //打印异常信息
return "MyException{" + detail + '}';
}
}
public class Test {
//可能会存在异常的方法
static void test(int a) throws MyException {
System.out.println("传递的参数为:"+a);
if (a > 10){
throw new MyException(a); //抛出
}
System.out.println("OK");
}
public static void main(String[] args) {
try {
test(12);
} catch (MyException e) {
System.out.println("MyException=>"+e);
}
}
}

本文来自博客园,by:{rubp},转载请注明原文链接:https://www.cnblogs.com/RRubp/p/16838518.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?