文章目录
继承
java
// 类
class 父类 {
}
class 子类 extends 父类 {
}
public class Animal {
private String name;
private int id;
public Animal(String myName, int myid) {
name = myName;
id = myid;
}
public void eat(){
System.out.println(name+"正在吃");
}
public void sleep(){
System.out.println(name+"正在睡");
}
public void introduction() {
System.out.println("大家好!我是" + id + "号" + name + ".");
}
}
public class Penguin extends Animal {
public Penguin(String myName, int myid) {
super(myName, myid);
}
}
public class Mouse extends Animal {
public Mouse(String myName, int myid) {
super(myName, myid);
}
}
// 接口
public interface A {
public void eat();
public void sleep();
}
public interface B {
public void show();
}
public class C implements A,B {
}
// super与this关键字
// super 关键字来实现对父类成员的访问,用来引用当前对象的父类。
// this 关键字指向自己的引用,引用当前对象所在的方法或构造函数所属的对象实例。
class Animal {
void eat() {
System.out.println("animal : eat");
}
}
class Dog extends Animal {
void eat() {
System.out.println("dog : eat");
}
void eatTest() {
this.eat(); // this 调用自己的方法
super.eat(); // super 调用父类方法
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Dog d = new Dog();
d.eatTest();
}
// animal : eat
// dog : eat
// animal : eat
}
需要注意的是 Java 不支持多继承,但支持多重继承。
重写与重载、抽象类、多态
java
// 重写
// 重写(Override)是指子类定义了一个与其父类中具有相同名称、参数列表和返回类型的方法,
// 并且子类方法的实现覆盖了父类方法的实现。 即外壳不变,核心重写!
class Animal{
public void move(){
System.out.println("动物可以移动");
}
}
class Dog extends Animal{
public void move(){
System.out.println("狗可以跑和走");
}
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal 对象
Animal b = new Dog(); // Dog 对象
a.move();// 执行 Animal 类的方法
b.move();//执行 Dog 类的方法
}
}
// 重载
// 重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
// 每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
public class Overloading {
public int test(){
System.out.println("test1");
return 1;
}
public void test(int a){
System.out.println("test2");
}
//以下两个参数类型顺序不同
public String test(int a,String s){
System.out.println("test3");
return "returntest3";
}
public String test(String s,int a){
System.out.println("test4");
return "returntest4";
}
public static void main(String[] args){
Overloading o = new Overloading();
System.out.println(o.test());
o.test(1);
System.out.println(o.test(1,"test3"));
System.out.println(o.test("test4",1));
}
}
// 抽象类和抽象方法
public abstract class Employee // 抽象类
{
private String name;
private String address;
private int number;
public abstract double computePay(); // 抽象方法
//其余代码
}
/* 文件名 : Salary.java */
public class Salary extends Employee
{
private double salary; // Annual salary
public double computePay()
{
System.out.println("Computing salary pay for " + getName());
return salary/52;
}
//其余代码
}
// 多态
// 当使用多态方式调用方法时,首先检查父类中是否有该方法,
// 如果没有,则编译错误;如果有,再去调用子类的同名方法。
// 多态的视线方式:1. 重写 2. 接口 3. 抽象类和抽象方法
public class Test {
public static void main(String[] args) {
show(new Cat()); // 以 Cat 对象调用 show 方法
show(new Dog()); // 以 Dog 对象调用 show 方法
Animal a = new Cat(); // 向上转型
a.eat(); // 调用的是 Cat 的 eat
Cat c = (Cat)a; // 向下转型
c.work(); // 调用的是 Cat 的 work
}
public static void show(Animal a) {
a.eat();
// 类型判断
if (a instanceof Cat) { // 猫做的事情
Cat c = (Cat)a;
c.work();
} else if (a instanceof Dog) { // 狗做的事情
Dog c = (Dog)a;
c.work();
}
}
}
abstract class Animal {
abstract void eat();
}
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
public void work() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨头");
}
public void work() {
System.out.println("看家");
}
}
封装、接口、枚举
java
// 封装
// 在面向对象程式设计方法中,封装(英语:Encapsulation)是指
// 一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。
// 封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。
// 要访问该类的代码和数据,必须通过严格的接口控制。具体例子此处略
// 接口
// 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract
// (只能是 public abstract,其他修饰符都会报错)。
// 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量
// (并且只能是 public,用 private 修饰会报编译错误)。
// 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。
// 注:JDK 1.8 以后,接口里可以有静态方法和方法体了。
// 注:JDK 1.8 以后,接口允许包含具体实现的方法,该方法称为"默认方法",默认方法使用
// default 关键字修饰。更多内容可参考 Java 8 默认方法。
// 注:JDK 1.9 以后,允许将方法定义为 private,使得某些复用的代码不会把方法暴露出去。
[可见度] interface 接口名称 [extends 其他的接口名] {
// 声明变量
// 抽象方法
}
...implements 接口名称[, 其他接口名称, 其他接口名称..., ...] ...
/* 文件名 : Animal.java */
interface Animal {
public void eat();
public void travel();
}
/* 文件名 : MammalInt.java */
public class MammalInt implements Animal{
public void eat(){
System.out.println("Mammal eats");
}
public void travel(){
System.out.println("Mammal travels");
}
public int noOfLegs(){
return 0;
}
public static void main(String args[]){
MammalInt m = new MammalInt();
m.eat();
m.travel();
}
}
// 接口的继承
// 文件名: Sports.java
public interface Sports
{
public void setHomeTeam(String name);
public void setVisitingTeam(String name);
}
// 文件名: Football.java
public interface Football extends Sports
{
public void homeTeamScored(int points);
public void visitingTeamScored(int points);
public void endOfQuarter(int quarter);
}
// 文件名: Hockey.java
public interface Hockey extends Sports
{
public void homeGoalScored();
public void visitingGoalScored();
public void endOfPeriod(int period);
public void overtimePeriod(int ot);
}
// 接口的多继承
public interface Hockey extends Sports, Event
// 枚举
enum Color
{
RED, GREEN, BLUE;
}
public class Test
{
// 执行输出结果
public static void main(String[] args)
{
Color c1 = Color.RED;
System.out.println(c1);
// 迭代枚举元素
for (Color myVar : Color.values()) {
System.out.println(myVar);
}
}
}
// switch中使用枚举类
enum Color
{
RED, GREEN, BLUE;
}
public class MyClass {
public static void main(String[] args) {
Color myVar = Color.BLUE;
switch(myVar) {
case RED:
System.out.println("红色");
break;
case GREEN:
System.out.println("绿色");
break;
case BLUE:
System.out.println("蓝色");
break;
}
}
}
// values(), ordinal() 和 valueOf() 方法
// values() 返回枚举类中所有的值。
// ordinal()方法可以找到每个枚举常量的索引,就像数组索引一样。
// valueOf()方法返回指定字符串值的枚举常量。
enum Color
{
RED, GREEN, BLUE;
}
public class Test
{
public static void main(String[] args)
{
// 调用 values()
Color[] arr = Color.values();
// 迭代枚举
for (Color col : arr)
{
// 查看索引
System.out.println(col + " at index " + col.ordinal());
}
// 使用 valueOf() 返回枚举常量,不存在的会报错 IllegalArgumentException
System.out.println(Color.valueOf("RED"));
// System.out.println(Color.valueOf("WHITE"));
}
// RED at index 0
// GREEN at index 1
// BLUE at index 2
// RED
}
// 枚举类成员
enum Color
{
RED, GREEN, BLUE;
// 构造函数
private Color()
{
System.out.println("Constructor called for : " + this.toString());
}
public void colorInfo()
{
System.out.println("Universal Color");
}
}
public class Test
{
// 输出
public static void main(String[] args)
{
Color c1 = Color.RED;
System.out.println(c1);
c1.colorInfo();
}
// Constructor called for : RED
// Constructor called for : GREEN
// Constructor called for : BLUE
// RED
// Universal Color
}
// 枚举类补充说明
// 枚举类不会在程序一启动时就加载,而是"延迟"到代码中第一次用到它
// (比如访问 Color.RED)的那一刻,JVM 才会去加载并初始化这个类。
// 一旦触发了初始化,JVM 会一次性把枚举类中定义的所有常量(RED, GREEN, BLUE...)全部创建出来。
包、反射
java
// 包
package pkg1[.pkg2[.pkg3...]];
import package1[.package2...].(classname|*);
package net.java.util;
public class Something{
...
}
// 第一行非注释行是 package 语句
package com.example;
// import 语句引入其他包中的类
import java.util.ArrayList;
import java.util.List;
// 类的定义
public class MyClass {
// 类的成员和方法
}
// 反射
// Java 反射(Reflection)是一个强大的特性,它允许程序在运行时
// 查询、访问和修改类、接口、字段和方法的信息。反射提供了一种动态地操作类的能力,
// 这在很多框架和库中被广泛使用,例如Spring框架的依赖注入。
// 获取Class对象
// 通过类字面量
Class<?> clazz = String.class;
// 通过对象实例
String str = "Hello";
Class<?> clazz = str.getClass();
// 通过Class.forName()方法
Class<?> clazz = Class.forName("java.lang.String");
// 创建对象
// 使用反射动态创建对象
Class<?> clazz = Class.forName("java.lang.String");
Object obj = clazz.getDeclaredConstructor().newInstance();
// 访问字段
// 可以通过反射访问和修改类的字段
Class<?> clazz = Person.class;
Field field = clazz.getDeclaredField("name");
field.setAccessible(true); // 如果字段是私有的,需要设置为可访问
Object value = field.get(personInstance); // 获取字段值
field.set(personInstance, "New Name"); // 设置字段值
// 调用方法
Class<?> clazz = Person.class;
Method method = clazz.getMethod("sayHello");
method.invoke(personInstance);
Method methodWithArgs = clazz.getMethod("greet", String.class);
methodWithArgs.invoke(personInstance, "World");
// 获取构造函数
Class<?> clazz = Person.class;
Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
Object obj = constructor.newInstance("John", 30);
// 获取接口和父类
Class<?> clazz = Person.class;
// 获取所有接口
Class<?>[] interfaces = clazz.getInterfaces();
for (Class<?> i : interfaces) {
System.out.println("Interface: " + i.getName());
}
// 获取父类
Class<?> superClass = clazz.getSuperclass();
System.out.println("Superclass: " + superClass.getName());
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectionExample {
public static void main(String[] args) throws Exception {
// 获取 Class 对象
Class<?> clazz = Person.class;
// 创建对象
Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
Object person = constructor.newInstance("John", 30);
// 访问字段
Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true);
System.out.println("Name: " + nameField.get(person));
// 修改字段
nameField.set(person, "Doe");
System.out.println("Updated Name: " + nameField.get(person));
// 调用方法
Method greetMethod = clazz.getMethod("greet", String.class);
greetMethod.invoke(person, "World");
}
// Name: John
// Updated Name: Doe
// Doe says: World
}
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void greet(String message) {
System.out.println(name + " says: " + message);
}
}
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
public class ReflectionExample {
public static void main(String[] args) throws Exception {
// 获取 Class 对象
Class<?> clazz = Car.class;
// 创建 Car 对象
Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
Object car = constructor.newInstance("Toyota", 2020);
// 访问和修改字段
Field modelField = clazz.getDeclaredField("model");
Field yearField = clazz.getDeclaredField("year");
// 设置字段为可访问(如果字段是私有的)
modelField.setAccessible(true);
yearField.setAccessible(true);
// 打印原始字段值
System.out.println("Original Model: " + modelField.get(car));
System.out.println("Original Year: " + yearField.get(car));
// 修改字段值
modelField.set(car, "Honda");
yearField.set(car, 2024);
// 打印修改后的字段值
System.out.println("Updated Model: " + modelField.get(car));
System.out.println("Updated Year: " + yearField.get(car));
// 调用方法
Method startMethod = clazz.getMethod("start");
startMethod.invoke(car);
}
// Original Model: Toyota
// Original Year: 2020
// Updated Model: Honda
// Updated Year: 2024
// The Honda car of year 2024 is starting.
}
class Car {
private String model;
private int year;
public Car(String model, int year) {
this.model = model;
this.year = year;
}
public void start() {
System.out.println("The " + model + " car of year " + year + " is starting.");
}
}
在 Java 安全领域,反射常被比喻为一把**"万能钥匙"或"双刃剑"**。它赋予了代码在运行时"无视规则"的能力。如果这把钥匙落入了攻击者手中(例如通过恶意输入触发了反射),后果确实是灾难性的。
以下是 java.lang.reflect 包中的主要类和接口的详细介绍:
- Class 类
功能:表示类的对象,提供了获取类信息的方法,如字段、方法、构造函数等。
主要方法:
getFields():获取所有公共字段。getDeclaredFields():获取所有声明的字段,包括私有字段。getMethods():获取所有公共方法。getDeclaredMethods():获取所有声明的方法,包括私有方法。getConstructors():获取所有公共构造函数。getDeclaredConstructors():获取所有声明的构造函数,包括私有构造函数。getSuperclass():获取类的父类。getInterfaces():获取类实现的所有接口。
- Field 类
功能:表示类的字段(属性),提供了访问和修改字段值的方法。
主要方法:
get(Object obj):获取指定对象的字段值。set(Object obj, Object value):设置指定对象的字段值。getType():获取字段的数据类型。getModifiers():获取字段的修饰符(如 public、private)。
- Method 类
功能:表示类的方法,提供了调用方法的能力。
主要方法:
invoke(Object obj, Object... args):调用指定对象的方法。getReturnType():获取方法的返回类型。getParameterTypes():获取方法的参数类型。getModifiers():获取方法的修饰符(如 public、private)。
- Constructor 类
功能:表示类的构造函数,提供了创建对象的能力。
主要方法:
newInstance(Object... initargs):创建一个新实例,使用指定的构造函数参数。getParameterTypes():获取构造函数的参数类型。getModifiers():获取构造函数的修饰符(如 public、private)。