大学时的java不傻瓜笔记-1
第一课碎碎念
- C语言是JAVA语言的语法基础,学过C语言就能看懂基本JAVA语言程序
- Android是利用Java开发的,Java中的大部分可以在Android中运行
- Android不是一门语言,而是一种操作系统
基础概念
正数的补码就是其本身,负数的补码就是取反。
栈,数据结构,先进后出。
队列,先进先出。
一个程序只有运行结束才会退出来
float a=1.2f;
double b=1.2345d;
a=(float)b;
int d,c=5;
d= c++; //d=5,c=6
d= ++c; //d=6,c=6
条件取反的时候,or和and要相互转换。
异或也叫半加运算,其运算法则相当于不带进位的二进制加法:二进制下用1表示真,0表示假,则异或的运算法则为:0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同为0,异为1),这些法则与加法是相同的,只是不带进位,所以异或常被认作不进位加法。
if (a>b?a=10:a=100);
for循环在没有循环的时候就知道会循环多少次,在不知道要循环多少次的时候使用while。
Java:OOP面向对象的程序设计。
C面向过程。
面向对象的思想,以装潢为例,就是寻找电工,泥瓦匠等工作人员,面向过程则是对于装潢中的各个步骤。
学习Java基本概念一定要很清楚
Java类
类(抽象的)是相关数据与方法的(抽象)集合。
对象(具体的)该类的实例。
命名要用驼峰法,要有意义,最好使用英文。
- 类名
- 字段
- 方法
类的名称大写开头,字段的名称小写开头
语句只能出现在方法内
class 类名{
int 字段;
void 方法名(形参){
语句;//这就是方法
//方法中有,方法名,形参,返回值return(void没有)
}
}
字段和变量很像 但是字段处于类下面,而变量在方法下。在eclipse中,字段会标蓝
实例化 将一个抽象的类具体到一个对象上
新建类和构造方法
步骤就不放了,我要是哪一天点击什么菜单都想不起来也查不到的话,不如早日改行XD
package app04.myself;
public class Students {
public String namber;
public String name;
public String age;
public void display() {
System.out.println("学号:"+this.namber);
System.out.println("姓名:"+this.name);
System.out.println("年龄:"+this.age);
}
}
构造方法没有返回值,方法名和类名一样
public Students(String namber, String name, int age) {
super();
this.namber = namber;
this.name = name;
this.age = age;
}
构造方法在new的时候,会自动调用
Students xxx=new Students("12334","xxx",20);
再创建一个无参的构造方法。如果本身不写有参构造方法,系统会自动写一个无参构造方法,但是如果我们写了有参构造方法,系统就不会自动写一个无参构造方法。有时子类会用到无参。
Java 程序在执行子类的构造方法之前,如果没有用 super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。
详细查阅书本P39,如果想不起来书放在哪里了就看一看书桌左侧的柜子(柜子,不是抽屉(换地方了记得来改
内存分为两块,栈和堆,基本变量放在栈里。
封装
包是用来分类放置类的。
面向对象的程序设计的特点:封装、继承、多态
如果一个类相当于一个银行,存钱的时候钱存在什么地方-知道一个存取的方法,但不知道具体存钱的地方细则-这就是封装(留下方法,屏蔽细节)。
封装的第一步,字段内部可见外部并不可见,private 在本类中可以调用,其他类中看不见 ,字段变成私有。
封装第二步,public的方法可以在其他类当中使用。
//修改名字
public void steName(String name)
{
this.name=name;
}
//取
public string getName()
{
return this.name;
}
优点:屏蔽复杂度,方便升级
多态
多态(overload重载,override覆盖)
覆盖是多态(可能有误 没听清楚)
重载,一部分理论认为重载不属于多态,一部分认为重载属于多态。
在同一个类中,允许一个方法的名称相同,但是参数的类型个数不同。
返回值不能作为区分重载不同方法的要素。
构造方法也可以重载。
一般构造方法的时候会给一个没有参数的重载(?讲子类的时候细讲)
有返回值的方法不复制,程序也可以允许。
垃圾收集,销毁不再使用的对象并释放内存,不再使用的对象定义为那些不再被引用的对象,或者其引用已经超出作用域的对象。
↑堆中没有被栈中的地址指向的就是垃圾。
字符串不断赋值的时候,会把原先的值变成垃圾。
继承
覆盖发生在父类和子类之间
extends,扩展,继承是类实现扩充的一个方法。
package app07;
class Animal {
public float weight;
public void eat() {
}
}
class Bird extends Animal {
//Bird是Animal的子类,Animal是Bird的父类(超类)
//Animal中可以继承的字段方法他都有,同时还具有单独属于Bird的字段方法
public int numberOfWings = 2;
public void fly() {
}
}
class Fish extends Animal {
public int numberOfFins = 2;
public void swim() {
}
}
class Dog extends Animal {
public int numberOfLegs = 4;
public void walk() {
}
}
子类反过来也可以扩展,除非他是final使得它不能扩展。
所有Java类都不用显式地扩展一个父类,而是会自动继承了java.lang.Object类(是所有类的父亲(自动))。
在Java中,一个类只能有一个父类,不能访问父类的私有方法,在一个包中的时候可以访问default方法。
方法覆盖
子类重写(方法的名称、参数、返回值都一样,功能不一样)父类已经有的办法
父类的方法依旧存在,只是在子类中调用的时候不会调用到父类的方法
package app07;
public class Box {
public int length;
public int width;
public int height;
public Box(int length, int width, int height) {
this.length = length;
this.width = width;
this.height = height;
}
@Override //覆盖 父类中一定要有下面写到的方法
public String toString() { //方法不变,但程序内容会改变
return "I am a Box.";
}
@Override
public Object clone() {
return new Box(1, 1, 1);
}
}
访问控制符
控制访问范围
同一个类 | 同一个包 | 不同包的子类 | 所有 | |
---|---|---|---|---|
private | ✓ | |||
default(不写) | ✓ | ✓ | ||
protected | ✓ | ✓ | ✓ | |
public | ✓ | ✓ | ✓ | ✓ |
如果方法是private,也就说方法只能在本类当中的其他方法中调用。
this关键字
在引用当前对象的任何方法或构造方法时使用this(在本类中代表本类对象)为了区分相同的对象名和本类名。
在类中使用其他类,很常见 。
当使用的类在一个包,默认允许。
使用包以外的类需要import。
写在package后面。
final变量
如果一个字段一旦赋值不能再变,常量。
final 类型 变量名(字段名)=赋值;
静态成员static
不需要new可以直接调用
内存从两块栈和堆变成三块:
- 栈(程序,变量,速度最快)
- 堆(最大的空间,new的东西,对象对应的具体的值(通过在栈中对象的地址访问),处理速度慢)
- 源空间 第三部分暂时成为 静态区域 放稳定常用的东西
static静态字段名称会变成斜体,会直接放在静态区域,以 类名.名称 0(0是它的值)的方式存放。
在静态所在的类没new之前也可以调用静态
调用方式 方法(类名.名称); 类.名称=赋值;
无论类new了几次,一个静态始终只有一个(字段)共用。
直接调用方法的好处:方便,最常用的方法static可以直接调用(静态方法)。
老师:从今天开始你们脑袋里面要有三块区域咯!
我:从今天开始我的脑袋要开始头晕啦!
静态方法也被成为类方法,不是静态的方法叫对象方法(使用对象调用)。
从一个静态方法的内部不能调用实例方法或者实例字段,因为实例需要new,而静态没有new,所以调用的时候实例没有地方存放,也就说当时没有这个实例。
在一个静态方法中可以直接调用其他静态。
静态final变量,不需要new的常量。
子类父类的强制转换
所有子类的对象都可以赋给超类对象。
向上强制转型 upcasting(安全)将子类的对象强制转型为父类的对象
可以把子类覆盖父类的方法带上去
//假设Child是Parent的子类
Child child = new Child();
Parent parent = child;
parent引用变量的时候不能访问那些只能在Child中可以使用的成员。
在父类中引用的子类对象可以强制转回子类,向下强制转换 downcasting(不安全:从哪儿来回哪儿去)。
超类强制转换为子类。向下强制转换只能转回对象本身所在的子类当中。
只有当父类的引用已经指向子类的一个实例的时候,才允许将子类向下强制转型。
Child child = new Child();
Parent parent = child;
Child child2=(Child)parent;
final类,类不能继承
final方法,方法不能被覆盖
final字段,字段不能改动
instanceof操作符
测试一个对象是否是一个特定的类型(查看对象是否存在于选定的类里)。
if(objectReference instanceof type)
实例:
//if会返回true
String s = "Holle";
if(s instanceof java.lang.String){}
//if会返回falseString s = null;
if(s instanceof java.lang.String){}
//例如 Child是Parent是子类
Child child = new Child();
if(child instanceof Parent){}//会返回true
这个关键字在向下强制转换的时候判断对象属于哪个子类很有用。
语法上没有错误不代表语义上没有错误,语法在编译阶段没有错误,但是在运行时会因为语义错误无法执行。
调用超类的隐藏方法
超类的隐藏方法:超类中被覆盖的方法
接口和抽象类
接口(interface),基类,抽象类
类 extends 类
类 implements 接口1,接口2
接口 extends 接口1,接口2
接口
package app10;
public interface Printable { //接口
public void print(Object o); //抽象方法 表示定义了一个print的方法,但是没有特地的方法
}
抽象方法有方法名,参数定义,返回值定义;没有功能实现。(如果后面不是“;”而是{}则表示为空的功能,是有功能的。)抽象 abstract
接口是“规范” 是服务提供者和服务使用者之间的协议。
比如,不同地区银行的利息算法都不一样,但是总行设定好了计算利息的方法名,参数,返回值,支行所使用计算利息的方法都使用总行制定好的规范。
接口可以通过子类继承去覆盖方法产生功能。
编程在顶层不知道细节但是需要规范的时候,都可以使用接口。
implements 实现
Printable是接口print存在的接口 ↑
CanonDriver是↓这个类
package app10;
public class CanonDriver implements Printable {
@Override
public void print(Object obj) {
System.out.println("this is CanonDriver");// code that does the printing
}
}
子类可以/不可以覆盖父类,子类必须覆盖接口才可以使用。
抽象方法在子类中被覆盖。
有了接口 底下所有的方法都会按照相应的名字去设定方法。
接口中的字段必须初始化(有初值),必须是(隐式的)公有的public、静态的static、final的
隐式-即使不声明也会是这三种状态。
接口中的字段也属于规范,任何方法都可以直接调用且不可更改。
接口中什么时候添加字段?在需要发布一些大家通用的参数情况下,接口中才会添加字段。
在接口中,如果两个字段拥有相同的名称会发生编译器错误,但是接口可以从其超接口继承多个具有相同名称的字段。
接口一旦发布,就不能添加新的方法,否则已经发布的版本就会报错。
接口的扩充不允许向上不兼容。
接口支持继承extends,接口的升级只能用继承。目的:为了安全地给一个接口添加功能,而不会破坏原有的代码。接口允许一次继承多个接口。
程序必须向上兼容
接口中的默认方法,如果扩展所有的接口,可能会导致接口的数目倍增,而且接口可能产生奇怪的名字。
JDK 1.8 以后,接口中可以添加默认发放(例如功能为空{ } 的方法,使用时进行覆盖)接口的默认方法是带有实现的方法,实现了接口的一个类,不一定必须实现默认方法,这意味着可以给接口添加新的方法而不会引起向后兼容的问题。
为了让接口中的方法成为默认方法,default关键字不可以省略,并且不是使用“;”结束 ,而是{ }
接口中的静态方法 可以使用接口名.静态方法名 Java 8 之后,接口中可以带有静态的方法,以便和接口相关的所有静态方法都可以写入接口。需要加上关键字static,默认公有。
基类
实现类必须覆盖接口中的所有抽象方法,当只需要其中一部分方法时可以创建一个泛型的实现类,它使用默认代码覆盖了接口中的抽象方法,然后一个实现类可以扩展这个泛型类,只需要覆盖想用的方法。
基类实现接口,覆盖的抽象方法功能为空。实现类继承基类,对于自己要使用的方法进行覆盖。
目的:减少用户代码量。
抽象类
一个类中同时包含抽象方法,abstract和非抽象方法。
类要携带 abstract关键字,类中的抽象方法需要携带 abstract关键字。
类要携带 abstract关键字 类中的抽象方法需要携带 abstract关键字。
实例
People类
package test1;
/**
* 1.基本类的设计,包含字段方法 2.方法的重载overload(两个speech) 3.封装,Source-Getters and setters
* 4.构造方法,有参/无参 Source-Fields 5.无参留给子类
*/
public class People {
private String name; // 姓名
private int age; // 年龄
private String gender; // 性别
public People(String name, int age, String gender) {
// super();调用超类的无参
this.name = name;
this.age = age;
this.gender = gender;
}
public People() {
super();
}
public void speech() {
System.out.println("People speech");
}
// 重载
public void speech(String s) {
System.out.println(s + ":People speech");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
Student类
package test1;
/**
* 1.完成Student对People的继承,Student可以访问People的字段 2.静态字段,记录学生总数 3.在构造方法中,添加People的参数
* 4.覆盖方法 soure-Override 5.覆盖InterfaceShow接口中的display抽象方法
*/
public class Student extends People implements InterfaceShow {
private String number; // 学号
private int avg; // 平均成绩
public static int studentTotal = 0; // 在构造方法中添加
public Student() {
studentTotal++;
}
public Student(String name, int age, String gender, String number, int avg) {
super(name, age, gender);
this.number = number;
this.avg = avg;
studentTotal++;
}
@Override
public void speech() {
System.out.println("Student speech");
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public int getAvg() {
return avg;
}
public void setAvg(int avg) {
this.avg = avg;
}
@Override
public void display() {
System.out.println("【学生】\n姓名:" + this.getName() + "\t年龄:" + this.getAge() + "\t性别:" + this.getGender() + "\t学号:"
+ this.number + "\t成绩:" + this.avg);
}
}
Teacher类
package test1;
public class Teacher extends People {
private String employeeNumber; // 教师号
private int salary; // 工资
public static int teacherTotal = 0; // 在构造方法中添加
public Teacher() {
teacherTotal++;
}
public Teacher(String name, int age, String gender, String employeeNumber, int salary) {
super(name, age, gender);
this.employeeNumber = employeeNumber;
this.salary = salary;
teacherTotal++;
}
public String getNumber() {
return employeeNumber;
}
public void setNumber(String employeeNumber) {
this.employeeNumber = employeeNumber;
}
public int getWages() {
return salary;
}
public void setWages(int salary) {
this.salary = salary;
}
public static int getTeacherTotal() {
return teacherTotal;
}
public static void setTeacherTotal(int teacherTotal) {
Teacher.teacherTotal = teacherTotal;
}
@Override
public void speech() {
System.out.println("Teach speech");
}
}
InterfaceShow接口
package test1;
/**
* 1.设置接口和抽象方法
*
* @author Administrator
*
*/
public interface InterfaceShow {
public void display();
}
Client类
package test1;
public class Client {
/*
* 当student对象时,执行student的speech
* 当teacher对象时,执行teacher的speech
*/
public static void doSpeech(People people)
{
people.speech();
}
/*
* 当student对象时,执行InterfaceShow的display
* 当teacher对象时,执行InterfaceShow的display
*/
public static void doDispaly(InterfaceShow interfaceShow)
{
interfaceShow.display();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Student ljw = new Student();
ljw.setName("林佳雯");
ljw.setAge(18);
ljw.setGender("女");
ljw.setNumber("206550202");
ljw.setAvg(90);
Student jxj =new Student("金雪佳", 18, "女", "2011111", 90);
ljw.speech();
jxj.speech(jxj.getName());
ljw.display();
//---
/*
* ljw是Student的对象,把Student的对象给People,是向上转换,可以把子类覆盖父类的方法带上去
*/
doSpeech(ljw);
doDispaly(ljw);
/*
* ljw是Student的对象,把Student的对象给InterfaceShow,是向上转换,可以把子类覆盖父类的方法带上去
*/
/*
* 向上转换的好处是在做上层编程的时候不需要考虑底层细节,顶层以接口的形式出现可以减少错误(因为没写会报错
*/
}
}
枚举
enum
可以杜绝人为赋值的错误;枚举值是一个对象,可以调用方法
package app12;
public enum CustomerType {
INDIVIDUAL,
ORGANIZATION
}
//这个枚举只有这两种枚举值
//赋值 变量=CustomerType.INDIVIDUAL
INDIVIDUAL, ORGANIZATION 是枚举值 默认静态字段 惯例大写,用逗号隔开。
在内部给enum一个是整数排序值,0表示第一个常量。
package app12;
public class Customer {
public String customerName;
public CustomerType customerType;
public String address;
}
package ch12.app12;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Customer c1=new Customer(); //新建一个顾客对象
c1.customerType=CustomerType.INDIVIDUAL;//顾客状态是散客
}
}
多重含义
package com.example;
public enum FuelEfficiency {
EFFICIENT(33, 55),
ACCEPTABLE(20, 32),
GAS_GUZZLER(1, 19);
//如何得到EFFICIENT中的33, 55两个值
//min和max分别对应两个值
//当对象赋值EFFICIENT时会把两个值分别使用构造方法进行放置
//通过get方法可以分别获得两个值
private int min;
private int max;
FuelEfficiency(int min, int max) {
this.min = min;
this.max = max;
}
public int getMin() {
return this.min;
}
public int getMax() {
return this.max;
}
}
package app12;
public class Shape {
private enum ShapeType { //内部类 定义一个ShapeType的枚举类
RECTANGLE, TRIANGLE, OVAL
};
private ShapeType type = ShapeType.RECTANGLE;
//定义一个字段 把RECTANGLE给他赋值
@Override
public String toString() {
if (this.type == ShapeType.RECTANGLE) {
return "Shape is rectangle";
}
if (this.type == ShapeType.TRIANGLE) {
return "Shape is triangle";
}
return "Shape is oval";
}
}
枚举,在Java5.0以后才有。
为了处理某一样东西的所有类型列举出来。
好处:
- 方便记忆
- 防止错误输入
- 具有多重含义
java.lang.Enum类
定义一个enum的时候,编译器创建了一个类定义,是java.lang.Enum类的直接子类。
具有以下属性:
- 没有公有的构造函数,使得不可能实例化
- 隐式地是静态的
- 每一个enum常量只有一个实例
- 可以在一个enum上调用values方法,以遍历其枚举值,该方法返回对象的一个数组。
- 可以在values所返回的对象上调用name和ordinal方法,以分别获取实例的名称和排序值
名称:.name是返回枚举值的字符串
排序值:.ordinal是返回枚举值的排序,排序从0开始
可以用for循环【foreach循环 与下标无关】来遍历enum中的值 首先要调用values方法,返回一个类似数组的对象,其中包含了指定enum的所有值。
CustomerType是枚举类,customerType是对象,是values返回的类似数组的对象
package ch12.app12.solft;
public enum Gradee {
FALSE,PASS,GOOD,EXCELLENT;
//一个Gradee的枚举类,里面有四个枚举值是FALSE,PASS,GOOD,EXCELLENT
//后面有语句时,枚举值会有要加分号
public static void main(String[] arg) {
System.out.println("所有成绩的种类为:");
for(Gradee m:Gradee.values())
System.out.println(m.name());
//name是返回枚举值的字符串
Student stu=new Student();
stu.name="zhangsan";
stu.gradee=Gradee.EXCELLENT;
stu.displayGradee();
System.out.println(stu.getClass().getName());
//返回相关Student的全部内容,把name(Student)打印成字符串
//输出结果是ch12.app12.solft.Student
}
}
class Student{
String name;
Gradee gradee;
public void displayGradee() {
System.out.println("名字:"+this.name+"成绩:"+this.gradee.name());
}
}
Class类---反射类
从技术上说,由于enum是一个类,一个enum可以有构造方法和方法。如果有构造方法,访问级别必须是私有或者默认的。如果一个enum定义包含了常量以外的其他内容,常量必须在其他内容前面并且以分号结束。
package ch12.app12;
public enum Weekend {
SATURDAY,
SUNDAY;
private Weekend() {
}
@Override
public String toString() {
return "Fun day " + (this.ordinal() + 1);
}
public static void main(String[] args) {
// print class name
System.out.println(Weekend.SATURDAY.getClass().getName());
//返回相关Weekend的全部内容,getName()打印成字符串
//通过这个可以知道weekend对象是哪个类的
//输出结果是ch12.app12.Weekend
for (Weekend w : Weekend.values()) {
System.out.println(w.name() + ": " + w);
//System.out.println(w.name() + ": " + w.toString());
//打印出对象等同于打印出对象toString
}
}
}
枚举类实现接口
-
在程序运行的区域:枚举值.接口方法(也需要进行覆盖)
-
在创建枚举值的时候:
枚举值{ public void 抽象方法名(){ 内容 } }
第一个方法是所有枚举值使用的抽象方法一样。
第二个方法是不同的枚举值用的抽象方法内容不同(每个枚举值都需要覆盖方法)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!