一个 Java 程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作。下面简要介绍下类、对象、方法和实例变量的概念。
- 对象:对象是类的一个实例,有状态和行为。例如,一条狗是一个对象,它的状态有:颜色、名字、品种;行为有:摇尾巴、叫、吃等。
- 类:类是一个模板,它描述一类对象的行为和状态。
- 方法:方法就是行为,一个类可以有很多方法。逻辑运算、数据修改以及所有动作都是在方法中完成的:做什么,怎么做。
- 实例变量:每个对象都有独特的实例变量,对象的状态由这些实例变量的值决定。
此外,在软件工程中,面向对象方法学的四基本思想为:对象,类,继承,消息通信;面向对象方法的三大特性为:封装,继承,多态;面向对象需要建立的三大模型为:对象模型、动态模型、功能模型。需要与以上四个概念分开。
public static void main(String[] args){ 内容 };
访问修饰符 关键字 返回类型 方法名 String类 字符串数组;
Java 注释主要有三种类型:
Java枚举类型:通过一枚一枚具体举例找到所需变量,enum后固定取值已定,只能在其中选择。
class FreshJuice {
enum FreshJuiceSize{ SMALL, MEDIUM , LARGE }
FreshJuiceSize size;
}
public class FreshJuiceTest {
public static void main(String[] args){
FreshJuice juice = new FreshJuice();
juice.size = FreshJuice.FreshJuiceSize.MEDIUM ;
}
}
Java类与对象:通过一张图
从上到下,我们知道《汽车》是一个类,所代表的是一系列车型的集合,即一个完整模板,模板有自定义状态和行为。对象是类细分后所形成的一套模型,比如白色涡轮增压保时捷飞翔,有状态:白色、行为:飞翔。
一个类可以包含以下类型变量:
- 局部变量(Local Variables):局部变量是在方法、构造函数或块内部声明的变量,它们在声明的方法、构造函数或块执行结束后被销毁,**局部变量在声明时需要初始化,否则会导致编译错误**。
- 实例变量(Instance Variables):实例变量是在类中声明,但在方法、构造函数或块之外,它们属于类的实例,每个类的实例都有自己的副本,如果不明确初始化,实例变量会被赋予默认值(数值类型为0,boolean类型为false,对象引用类型为null)。
- 静态变量或类变量(Class Variables):类变量是在类中用 static 关键字声明的变量,它们属于类而不是实例,所有该类的实例共享同一个类变量的值,类变量在类加载时被初始化,而且只初始化一次,静态变量可以用来存储整个程序都需要使用的数据,如配置信息、全局变量等。
- 参数变量(Parameters):参数是方法或构造函数声明中的变量,用于接收调用该方法或构造函数时传递的值,参数变量的作用域只限于方法内部。
public void gayblack(){
int age = 10;//局部变量,作用域在此方法中,在声明后必须初始化,否则编译不会通过,比如int age;
}
public class ExampleClass {
int instanceVar;//实例变量,可以不初始化,默认赋值0/FALSE/NULL
}
public class ExampleClass {
static int age = 10;/*类变量,只属于类,
静态变量在类加载时被创建,在整个程序运行期间都存在*/
}
public void setage(int parameterVar) {
//参数变量,只在此方法中有用
age = parameterVar;
}
public class RunoobTest {
private int instanceVar;// 成员变量
private static int staticVar;// 静态变量
public void method(int paramVar) { //参数变量
int localVar = 10;// 局部变量
instanceVar = localVar;
staticVar = paramVar;
System.out.println("成员变量: " + instanceVar);
System.out.println("静态变量: " + staticVar);
System.out.println("参数变量: " + paramVar);
System.out.println("局部变量: " + localVar);
}
public static void main(String[] args) {
RunoobTest v = new RunoobTest();
v.method(20);
}
}
输出结果:
成员变量: 10
静态变量: 20
参数变量: 20
局部变量: 10
静态变量可以用来存储整个程序都需要使用的数据,如配置信息、全局变量等。
如果一个静态变量依赖于另一个静态变量,那么它必须在后面定义。
public class MyClass {
public static int count = 0;
// 其他成员变量和方法
}
MyClass.count = 10; // 通过类名访问
MyClass obj = new MyClass();
obj.count = 20; // 通过实例名访问
get()方法是用来获取指定的私有成员变量的值,set()方法是用来设置指定的私有成员变量的值,get和set方法是Java中的一个重要概念,用于访问和修改对象的属性。在类内部定义private限制变量的作用域,用set和get方法来改变变量的值,该机制隐藏了代码实现细节,体现了数据的封装性,保证了代码的安全,同时也提升了数据的安全性。在对set和get方法的实现中,可以使用一些限定条件提升数据精确度。
class Student{
private string name;
private int score;
public void show(){
System.out.println("我的名字是" + name + ",我的成绩是"+ score + "分。")
}
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
public int getScore(){
return score;
}
public void setScore(int score){
if(score<0 && score >100){
this.score = 0;
} else{
this.score=score;
}
}
}
public class Test{
public static void main(String[] args){
Student s1=new Student();
Student s2=new Student();
s1.setName("jack");
s2.setName("black");
s1.setScore(100);
s2.setScore(60);
s1.show();
s2.show();
}
}
整型、实型(常量)、字符型数据可以混合运算。运算中,不同类型的数据先转化为同一类型,然后进行运算。
转换从低级到高级。
低 ------------------------------------> 高 byte,short,char—> int —> long—> float —> double
一个字节8位/两个字节16位/单一的16位Unicode字符/四个字节32位/八个字节64位/四个字节32位/八个字节64位
数据类型转换必须满足如下规则:
1. 不能对boolean类型进行类型转换。
2. 不能把对象类型转换成不相关类的对象。
3. 在把容量大的类型转换为容量小的类型时必须使用强制类型转换。
4. 转换过程中可能导致溢出或损失精度,例如:
int i =128; byte b = (byte)i;
因为 byte 类型是 8 位,最大值为127,所以当 int 强制转换为 byte 类型时,值 128 时候就会导致溢出。
5. 浮点数到整数的转换是通过舍弃小数得到,而不是四舍五入,例如:
(int)23.7 == 23; (int)-45.89f == -45
Java中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。
default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
public : 对所有类可见。使用对象:类、接口、变量、方法
**protected** : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
我们可以通过以下表来说明访问权限:
protected关键需要理解的是同一包内和所有子类可见,这两点只要满足就可以。我们可以通过以下几个关于protected方法可见性的例子来进一步掌握protected关键字。
代码1:对于(1)而言,clone()方法来自于类MyObject2本身,因此其可见性为包p2及MyObject2的子类,虽然Test2是MyObject2的子类,但在Test2中实例化myobj2不能访问基类MyObject2的protected方法clone(),因此编译不通过;对于(2)而言,由于Test2继承于基类MyObject2,在Test2类作用域内部实现clone()因此编译通过。
package p2;
class MyObject2 {
protected Object clone() throws CloneNotSupportedException{
return super.clone();
}
}
package p22;
public class Test2 extends MyObject2 {
public static void main(String args[]) {
MyObject2 obj = new MyObject2();
obj.clone(); // Compile Error ----(1)
Test2 tobj = new Test2();
tobj.clone(); // Complie OK ----(2)
}
}
代码2:对于(1)而言,clone()方法来自于类MyObject5,因此其可见性为包p5及其子类(此处没有子类),而类Test5也在包p5中,因此满足可见性,编译通过。
package p5;
class MyObject5 {
protected Object clone() throws CloneNotSupportedException{
return super.clone();
}
}
public class Test5 {
public static void main(String[] args) throws CloneNotSupportedException {
MyObject5 obj = new MyObject5();
obj.clone(); // Compile OK ----(1)
}
}
代码3:对于(1)而言,clone()方法来自于类Object,因此该clone()方法可见性为包java.lang及其子类Test7,由于类MyObject7不在此范围内,因此不满足可见性,编译不通过。
package p7;
class MyObject7 extends Test7 {
public static void main(String[] args) {
Test7 test = new Test7();
test.clone(); // Compile Error ----- (1)
}
}
public class Test7 {
}
代码4:首先看(1)(3),其中的f()方法从类Father1继承而来,其可见性是包p1及其子类Son1和Son11,而由于调用f()方法的类Test1所在的包也是p1,因此(1)(3)处编译通过。其次看(2)(4),其中的clone()方法的可见性是java.lang包及其所有子类,对于语句"son1.clone();"和"son11.clone();",二者的clone()在类Son1、Son11中是可见的,但对Test1是不可见的,因此(2)(4)处编译不通过。
package p1;
public class Father1 {
protected void f() {} // 父类Father1中的protected方法
}
package p1;
public class Son1 extends Father1 {}
package p11;
public class Son11 extends Father1{}
package p1;
public class Test1 {
public static void main(String[] args) {
Son1 son1 = new Son1();
son1.f(); // Compile OK ----(1)
son1.clone(); // Compile Error ----(2)
Son11 son = new Son11();
son11.f(); // Compile OK ----(3)
son11.clone(); // Compile Error ----(4)
}
}
这里注意将代码4和代码1做对比,代码2和3容易理解。
为了实现一些其他的功能,Java 也提供了许多非访问修饰符。
static 修饰符,用来修饰类方法和类变量,局部变量不能被声明为 static 变量。类方法又叫static方法,是属于当前整个类的,而不是属于某个实例的,只能处理static域或调用static方法,类方法可以直接通过类名调用,不需要先初始化类的实例,如果一个静态变量依赖于另一个静态变量,那么它必须在后面定义。
public class Demo {
public static int s=10;
//类变量,所有对象共享同一份数据,可以通过类名来访问静态变量,也可以通过实例名来访问静态变量
float a;
//实例方法
void sum(float num1,float num2){
a = Max(num1,num2);
}
//类方法
static float Max(float num1,float num2){
return num1 <= num2 ? num2 :num1;
}
public static void main(String[] args) {
Demo demo =new Demo();
demo.sum(22,33); //实例方法必需先初始化类的实例,然后通过类的实例才能调用
Demo.Max(12,9); // 类方法可以直接通过类名调用
}
}
final 修饰符,用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的:final变量一旦赋值后,不能被重新赋值。被 final 修饰的实例变量必须显式指定初始值; final 方法可以被子类继承,但是不能被子类重写;final 类不能被继承,没有类能够继承 final 类的任何特性。
abstract 修饰符,用来创建抽象类和抽象方法,任何继承抽象类的子类必须实现父类的所有抽象方法,除非该子类也是抽象类。
synchronized 和 volatile 修饰符,主要用于线程的编程,synchronized 关键字声明的方法同一时间只能被一个线程访问。synchronized 修饰符可以应用于四个访问修饰符。volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。
public class selfAddMinus{
public static void main(String[] args){
int a = 5;
int b = 5;
int x = 2*++a;
int y = 2*b++;
System.out.println("自增运算符前缀运算后a="+a+",x="+x);
System.out.println("自增运算符后缀运算后b="+b+",y="+y);
}
}
自增运算符前缀运算后a=6,x=12,++a是让a先自增之后再参与运算,最终a的值总要增。
自增运算符后缀运算后b=6,y=10,b++是让b先参与运算之后再自增,最终b的值总要增。
A = 0011 1100 B = 0000 1101
位运算符使用少,记住^:异或和>>>右移补零 使用方法即可,其他是常识。
当使用与逻辑运算符时,在两个操作数都为true时,结果才为true,但是当得到第一个操作为false时,其结果就必定是false,这时候就不会再判断第二个操作了。
public class LuoJi{
public static void main(String[] args){
int a = 5;//定义一个变量;
boolean b = (a<4)&&(a++<10);
System.out.println("使用短路逻辑运算符的结果为"+b);
System.out.println("a的结果为"+a);
}
}
解析: 该程序使用到了短路逻辑运算符(&&),首先判断 a<4 的结果为 false,则 b 的结果必定是 false,所以不再执行第二个操作 a++<10 的判断,所以 a 的值为 5。
b = (a == 1) ? 20 : 30;//如果 a 等于 1 成立,则设置 b 为 20,否则为 30。
该运算符用于操作对象实例,检查该对象是否是一个特定类型(类类型或接口类型)。
String name = "James"; boolean result = name instanceof String; // 由于 name 是 String 类型,所以返回真
参考于菜鸟教程:菜鸟教程 - 学的不仅是技术,更是梦想! (runoob.com)
如有错误请评论区指点,感谢!