Java编程拾遗『反射』_java getannotatedinterfaces-程序员宅基地

技术标签: Java  Java编程拾遗  java  Java 基础  反射  

在大多数场景下,我们在代码编写时,我们一般都知道所要使用的数据的具体类型,会根据类型创建对象,并使用对象的一些属性及方法。但是有些情况下,我们在编写代码时,无法确定要创建对象的具体类型,比如我要编写一个工厂类,通过运行时的输入信息,决定构建一个什么类型的对象,这时候在编译期就无法完成了。而反射就提供了一种机制,在运行时,而非编译时,动态获取类型的信息,比如接口信息、成员信息、方法信息、构造方法信息等,根据这些动态获取到的信息创建对象、访问/修改成员、调用方法等。本篇文章会简单介绍一下Java反射的机制的使用细节,及反射机制的一些应用。

1. Class类

我们都知道,一个.java文件在编译后会形成相应的一个或多个Class文件,这些Class文件中描述了类的各种信息,并且它们最终都需要被加载到虚拟机中才能被运行和使用。事实上,Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成了可以被虚拟机直接使用的Java类型——Class对象。每个已加载的类在内存都有一个对应的Class对象,每个对象都有指向它所属Class对象的引用。

1.1 获取Class对象

获取Class对象就是获取上述可以被虚拟机直接使用的Java类型,在Java中,对应的类是泛型类java.lang.Class。可以通过一下三种方式获取Class对象:

  • 调用类的class属性,比如String.class获取的就是String类对应的Class对象
  • 调用某个对象的getClass()方法,比如new String().getClass()
  • 调用Class.forName(String clazzName)静态方法

1.1.1 <类名>.class

通过类名可以获取类在Java虚拟机中对应的描述类的各种信息的Class对象,如下:

Class<String> cl = String.class;

除了类之外,接口也可以通过这种方式获取描述接口的各种信息的Class对象,如下:

Class<Comparable> cl = Comparable.class;

对于基本数据类型,也可以获取对应的Class对象,Class对象的类型参数为对应的包装类型,如下:

Class<Integer> intCl = int.class;
Class<Character> charCl = char.class;

总之,如果T是任意的Java类型,T.class都可以获取类型对应的类型信息。从这里也可以发现,其实Class对象实际上表示的就是一个类型,而这个类型并不一定是一种类,例如上面讲的int不是类,但是int.class是一个Class类型的对象。依此类推,Java中的各种数组、枚举类、甚至void都可以通过这种方式获取类型信息。

1.1.2 <对象>.getClass()

Java中所有类的父类Object中有一个方法,可以获取对象的类型信息,即getClass()方法,如下:

public final native Class<?> getClass()

Class是一个泛型类,有一个类型参数,getClass()并不知道具体的类型,所以返回Class<?>。

Employee e;
//……
Class cl = e.getClass();
System.out.println(cl.getName() + " " + e.getName());

Class对象的getName方法,返回该类的名字。上述如果e是一个雇员,将会打印出:

Employee zhuoli

如果e是经理,将会打印出:

Manager zhuoli

如果类在一个包里,包的名字也会作为类名的一部分,如下:

Date d = new Date();
String name = d.getClass().getName(); // name is set to "java.unit.Date"

注意,通过这种方式无法获取基本类型的类型信息,因为getClass()这种方式必须通过对象实例调用。

1.1.3 静态方法Class.forName(clazzName)

Class有一个静态方法forName,可以根据类名直接加载Class,获取Class对象,如下:

try {
    Class<?> cls = Class.forName("java.util.HashMap");
    System.out.println(cls.getName());
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

类名保存在字符串中,就可以通过forName方法获取类名对应类的类型信息。如果类名对应的类不存在,会抛出一个Checked Exception(受检查异常)——ClassNotFoundException。无论合适使用这个方法,都应该提供一个try-catch异常处理器。

1.2 Class方法说明

在Java中,用于提供反射的包java.lang.reflect中有三个重要的类Field、Method和Constructor,分别用来描述类的域、方法和构造器。获取了Class对象后,可以通过Class对象获取上述三个类的实例,通过实例在运行期进行动态调用。

1.2.1 名称信息

S.N. 方法 说明
1 public String getName() 返回类型名称,包括包信息,返回信息不友好
2 public String getSimpleName() 获取类型名称,不包括包信息
3 public String getCanonicalName() 返回Java语言规范定义的底层类的规范名称,返回信息较getName友好
4 public String getTypeName() Java8新引入的方法,返回此类型名称,与getName的区别在于数组类型的处理上
5 public Package getPackage() 返回类的包信息

它们之间的不同如下所示:

Class对象 getName getSimpleName getCanonicalName getTypeName getPackage
int.class int int int int null
int[].class [I int[] int[] int[] null
int[][].class [[I int[][] int[][] int[][] null
String.class java.lang.String String java.lang.String java.lang.String java.lang
String[].class [Ljava.lang.String; String[] java.lang.String[] java.lang.String[] null
HashMap.class java.util.HashMap HashMap java.util.HashMap java.util.HashMap java.util
Map.Entry.class java.util.Map$Entry Entry java.util.Map.Entry java.util.Map$Entry java.util

对于getName方法,如果类型是内部类,则使用“$”符号进行连接。如果类型是数组,则使用“[”来表示,数组是几维,“[”就有几个,对于引用类型数组最后会多一个“;”。getTypeName与getName的区别是在数组类型的处理上,如果是数组类型,会转换成友好的展示方式,如果非数组类型,则与getName返回相同。

1.2.2 成员变量信息

通过Class对象除了可以获取类型名称信息,还可以获取类型所表示类的成员变量。

S.N. 方法 说明
1 public Field getField(String name) 返回此Class对象对应类的指定名称的public成员变量
2 public Field[] getFields() throws SecurityException 返回此Class对象对应类的所有public成员变量,包括超类public成员变量
3 public Field getDeclaredField(String name) 返回此Class对象对应类的指定名称的成员变量,与成员变量访问权限无关
4 public Field[] getDeclaredFields() throws SecurityException 返回此Class对象对应类的全部成员变量,与成员变量的访问权限无关,不包括超类成员变量

1.2.3 方法信息

通过Class对象获取Class对象对应类的内部方法信息,如下:

S.N. 方法 说明
1 public Method getMethod(String name, Class<?>… parameterTypes) 返回此Class对象对应类的带指定形参的public方法,parameterTypes为参数类型
2 public Method[] getMethods() throws SecurityException 返回此Class对象所表示的类的所有public方法,包括超类public方法
3 public Method getDeclaredMethod(String name, Class<?>… parameterTypes) 返回此Class对象对应类的带指定形参的方法,与方法访问权限无关
4 public Method[] getDeclaredMethods() throws SecurityException 返回此Class对象对应类的全部方法,与方法的访问权限无关,不包括超类方法

1.2.4 构造器信息

通过Class对象获取Class对象对应类的构造器信息,如下:

S.N. 方法 说明
1 public Constructor<T> getConstructor(Class<?>… parameterTypes) 返回此Class对象对应类的带指定参数类型的public构造器
2 public Constructor<?>[] getConstructors() throws SecurityException 返回此Class对象对应类的所有public构造器,包括超类的public构造器
3 public Constructor<T> getDeclaredConstructor(Class<?>… parameterTypes) 返回此Class对象对应类的带指定参数类型的构造器,与构造器的访问权限无关
4 public Constructor<?>[] getDeclaredConstructors() throws SecurityException 返回此class对象对应类的所有构造器,与构造器的访问权限无关,不包括超类构造器

1.2.5 类注解信息

通过Class对象获取Class对象对应类的注解信息,如下:

S.N. 方法 说明
1 public <A extends Annotation> A getAnnotation(Class<A> annotationClass) 获取此Class对象对应类上的指定类型的Annotation
2 public Annotation[] getAnnotations() 获取此Class对象对应类上的所有Annotation
3 public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass) Java8新增的方法,获取此Class对象对应类上指定类型的多个Annotation,可获取重复注解
4 public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) Java8新增的方法,获取此Class对象对应类上的指定类型的Annotation
5 public Annotation[] getDeclaredAnnotations() 获取此Class对象对应类上的所有Annotation
6 public <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationClass) Java8新增的方法,功能与getDeclaredAnnotations注解相似,但可以获取重复注解

1.2.5 类信息

S.N. 方法 说明
1 public Class<?>[] getDeclaredClasses() throws SecurityException 获取Class对象对应类所有内部类Class对象
2 public Class<?> getDeclaringClass() throws SecurityException 获取Class对象对应类的外部类Class对象
3 public Class<?>[] getInterfaces() 获取Class对象对应类实现的接口Class对象
4 public AnnotatedType[] getAnnotatedInterfaces() Java8新增方法,获取Class对象对应类实现的所有带注解的接口类型
5 public Type[] getGenericInterfaces() 获取Class对象对应类实现的所有泛型接口类型
6 public native Class<? super T> getSuperclass() 获取Class对象对应类继承的父类Class对象
7 public AnnotatedType getAnnotatedSuperclass() Java8新增方法,获取Class对象对应类继承的带注解的父类类型
8 public Type getGenericSuperclass() 获取Class对象对应类继承的泛型类类型

1.2.6 类修饰符信息

S.N. 方法 说明
1 public native int getModifiers() 获取Class对象对应类的所有修饰符,修饰符由public、protected、private、final、static、abstract等对应的常量组成,返回的整数应使用Modifier工具类的方法来解码

2. 反射工具介绍

Java API中,包java.util.reflect下提供了很多用于反射的类,可以方便的使用上述成员信息、构造器信息、方法信息,分别对应包下的三个类Field、Constructor和Method。

2.1 Field类

上面讲过,可以通过Class对象获取对应类的成员变量,并且不难发现返回值类型为java.util.reflect包下的Field。通过Field对象可以对改成员变量进行设置访问权限、获取成员变量值、设置成员变量值等操作。下面看一下Field类的主要方法:

S.N. 方法 说明
1 public String getName() 返回成员变量名称
2 public int getModifiers() 返回成员变量修饰符,可以通过Modifier工具类的方法来解码
3 public Class<?> getType() 返回成员变量类型Class对象
4 public boolean isAccessible() 成员变量是否可访问,比如private成员变量调用此方法会返false
5 public void setAccessible(boolean flag) throws SecurityException 设置成员变量可访问,可以通过这种方式访问private成员变量
6 public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass)
public Annotation[] getDeclaredAnnotations()
获取方法注解,参考上面Class对象的同名方法
7 public boolean getBoolean(Object obj)
public byte getByte(Object obj)
public short getShort(Object obj)
public int getInt(Object obj)
public long getLong(Object obj)
public char getChar(Object obj)
public float getFloat(Object obj)
public double getDouble(Object obj)
获取指定对象obj中该基础类型成员变量的值
8 public Object get(Object obj) 获取指定对象obj中该成员变量的值,返回值类型为Object
9 public void setBoolean(Object obj, boolean z)
public void setByte(Object obj, byte b)
public void setShort(Object obj, short s)
public void setInt(Object obj, int i)
public void setLong(Object obj, long l)
public void setChar(Object obj, char c)
public void setFloat(Object obj, float f)
public void setDouble(Object obj, double d)
将指定对象obj中该基础类型成员变量设置为相应的值
10 public void set(Object obj, Object value) 将指定对象obj中该成员变量的值设为value

调用示例:

@Getter
@Setter
@AllArgsConstructor
public class Father {
    private String name;

    private Integer age;
}

@Getter
@Setter
@ToString
public class Son extends Father {
    private static final String CONSTANT_STRING = "constant";

    private Float score;

    private boolean isPass;

    public Son(String name, Integer age, Float score, Boolean isPass) {
        super(name, age);
        this.score = score;
        this.isPass = isPass;
    }
}
public static void main(String[] args) {
    
    Father son = new Son("zhuoli", 18, 95.0f, true);
    Field[] fields = son.getClass().getDeclaredFields();
    for (Field field : fields) {
        field.setAccessible(true);
        try {
            System.out.println(field.getName()+" - "+field.get(son));
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    System.out.println("-------------------");
    try {
        Field isPassField = son.getClass().getDeclaredField("isPass");
        isPassField.setAccessible(true);
        boolean isPass = isPassField.getBoolean(son);
        System.out.println("before change, isPass: " + isPass);
        isPassField.setBoolean(son, false); //设置对象son的isPass成员变量的值为false
        System.out.println(son);

        System.out.println("-------------------");
        Field scoreField = son.getClass().getDeclaredField("score");
        scoreField.setAccessible(true);
        Float score = (Float) scoreField.get(son);
        System.out.println("before change, score: " + score);
        scoreField.set(son, 99.9f); //设置对象son的score成员变量的值为99.9f
        System.out.println(son);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

运行结果:

CONSTANT_STRING - constant
score - 95.0
isPass - true
-------------------
before change, isPass: true
Son(score=95.0, isPass=false)
-------------------
before change, score: 95.0
Son(score=99.9, isPass=false)

2.2 Constructor类

上面讲过通过Class对象可以获取对应类的构造器信息,返回值类型为Constructor。通过Constructor实例,可以构造对象实例。同Field类相似,Constructor类中也有getName、getModifiers等方法,语言也是相似的。

S.N. 方法 说明
1 public String getName() 获取构造器名称
2 public int getModifiers() 获取构造器修饰符信息
3 public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
public Annotation[] getDeclaredAnnotations()
获取构造器注解
4 public Annotation[][] getParameterAnnotations() 获取构造器参数注解
5 public Class<?>[] getParameterTypes() 获取构造器参数类型
6 public int getParameterCount() 获取构造器参数个数,Java8新引入的方法
7 public void setAccessible(boolean flag) throws SecurityException 设置访问权限,继承自AccessibleObject
8 public T newInstance(Object … initargs) Construtor中最重要的一个方法,用于构造对象实例

下面重点看一下newInstance方法,如下:

public T newInstance(Object ... initargs)
        throws InstantiationException, IllegalAccessException,
               IllegalArgumentException, InvocationTargetException

可以通过如下方式调用:

try {
    Constructor<Son> constructor = Son.class.getDeclaredConstructor(String.class, Integer.class, Float.class, Boolean.class);
    Son son1 = constructor.newInstance("Michael", 19, 96.8f, true);
    System.out.println(son1);
} catch (Exception e) {
    e.printStackTrace();
}

运行结果:

Son(score=96.8, isPass=true)

说明成功通过Construtor构建了一个Son实例。

2.3 Method类

Method类的引用变量可以指向上面通过Class对象获取的成员方法信息,Method实例可以用来动态代用调用方法。首先看一下Method类中的常用方法:

S.N. 方法 说明
1 public String getName() 获取方法名称
2 public int getModifiers() 获取方法修饰符信息
3 public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
public Annotation[] getDeclaredAnnotations()
获取方法注解信息
4 public Annotation[][] getParameterAnnotations() 获取参数注解信息
5 public Class<?>[] getParameterTypes() 获取方法参数类型
6 public int getParameterCount() 获取方法参数个数,Java8新引入的方法
7 public Class<?> getReturnType() 获取方法返回值类型
8 public void setAccessible(boolean flag) throws SecurityException 设置访问权限,继承自AccessibleObject
9 public Object invoke(Object obj, Object… args) 调用方法,第一个参数为调用方法的对象,后面的可变参数为方法实参

invoke方法声明如下:

public Object invoke(Object obj, Object... args)
    throws IllegalAccessException, IllegalArgumentException,
       InvocationTargetException

可以通过如下方式调用:

try {
    Method method = Son.class.getMethod("getAge", null);
    Integer age = (Integer) method.invoke(son, null);
    System.out.println(age);
} catch (Exception e) {
    e.printStackTrace();
}

运行结果:

18

说明通过反射,成功调用了getAge方法。除了反射共有方法,还可以通过反射调用类的私有方法,假如getAge是私有方法,则可以通过如下方式反射调用:

try {
    Method method = Son.class.getMethod("getAge", null);
    method.setAccessible(true); //设置访问权限为可访问
    Integer age = (Integer) method.invoke(son, null);
    System.out.println(age);
} catch (Exception e) {
    e.printStackTrace();
}

最后讲一下关于修饰符Modifiers的问题,首先在Son类中添加一个静态方法,如下:

public static void modifiersTestMethod(String info) {
    System.out.println(info);
}

可以通过如下方式解析修饰符信息:

try {
    Method method = Son.class.getMethod("modifiersTestMethod", String.class);
    method.invoke(null, "test test test!");

    int modifierCode = method.getModifiers();
    System.out.println(Modifier.toString(modifierCode));
    System.out.println("isPublic: " + Modifier.isPublic(modifierCode));
    System.out.println("isStatic: " + Modifier.isStatic(modifierCode));
    System.out.println("isFinal: " + Modifier.isFinal(modifierCode));
    System.out.println("isVolatile: " + Modifier.isVolatile(modifierCode));
} catch (Exception e) {
    e.printStackTrace();
}

运行结果:

test test test!
public static
isPublic: true
isStatic: true
isFinal: false
isVolatile: false

2.4 Array类

除了上面讲的Field、Construtor和Method类,java.lang.reflect包中还有一个比较重要的类——Array,用于数组的一些反射支持,以便于统一处理多种类型的数组。

S.N. 方法 说明
1 public static native Object get(Object array, int index) 获取array index索引位置的元素
2 public static native byte getByte(Object array, int index)
public static native short getShort(Object array, int index)
public static native int getInt(Object array, int index)
public static native long getLong(Object array, int index)
public static native char getChar(Object array, int index)
public static native float getFloat(Object array, int index)
public static native double getDouble(Object array, int index)
public static native boolean getBoolean(Object array, int index)
获取基本类型array index索引位置的元素
3 public static native void set(Object array, int index, Object value) 设置array index索引位置元素值为value
4 public static native void setByte(Object array, int index, byte b)
public static native void setShort(Object array, int index, short s)
public static native void setInt(Object array, int index, int i)
public static native void setLong(Object array, int index, long l)
public static native void setChar(Object array, int index, char c)
public static native void setFloat(Object array, int index, float f)
public static native void setDouble(Object array, int index, double d)
public static native void setBoolean(Object array, int index, boolean z)
设置基本类型array index索引位置元素值为value
5 public static Object newInstance(Class<?> componentType, int length) 动态构造componentType类型,长度为length的数组

回想一下,工具类java.util.Arrays类中有一个方法copyOf,声明如下

public static <T> T[] copyOf(T[] original, int newLength)

可以实现数组复制,如果newLength大于原数组original长度,还可以实现对数组扩容的效果。现在我们也想写一个功能类似的数组扩容的通用方法,扩容10%,同时不希望手动去写那些扩展拷贝元素的代码。于是首先我们首先想到的是使用Object数组,实现通用的效果,然后通过System.arrayCopy代替手工的拷贝元素的操作,如下:

public static Object[] badArrayGrow(Object[] array) {
    int length = array.length;
    int newLength = length * 11 / 10;
    Object[] newArray = new Object[newLength];

    System.arraycopy(array, 0, newArray, 0, length);
    return newArray;
}

好像看起来是完全没问题的,使用时在讲Object数组转换成目标数组,如下:

Integer[] array = new Integer[10];
array[0] = 1;
array[1] = 2;
array[2] = 3;

Integer[] newArray1 = (Integer[]) ArrayUtil.badArrayGrow(array);
System.out.println(newArray1.length);

编译没有任何问题,但是在运行时,报错了,报错信息如下:

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;

因为Java数组会记住每个元素的类型,即创建数组时new表达式中使用的元素类型。将一个Integer[]临时转换成Object[]数组,然后再把它转换回来是可以的,但是一个从开始就是Object[]的数组是永远不能转换Integer[]数组。所以这种方式显然是不能达到扩容效果的,为了能够实现通用的数组代码,需要能够创建与原数组类型相同的新数组,这时候就可以通过上述java.lang.reflect包中的Array类提供的newInstance方法,构建特定类型的数组。所以对扩容方法进行改进,如下:

public static Object goodArrayGrow(Object[] array) {
    int newLength = array.length * 11 / 10;
    return Array.newInstance(array.getClass().getComponentType(), newLength);
}

如下调用:

Integer[] newArray2 = (Integer[]) ArrayUtil.goodArrayGrow(array);
System.out.println(newArray2.length);

运行结果:

11

扩容成功了,但是可以发现另一个问题,这个方法只能对对象类型数组扩容,对于基本类型数组,是无法使用的,一个基本类型数组时不能赋值给Object[]类型引用的。所以又对方法进行了改造,如下:

public static Object ultimateArrayGrow(Object array) {
    Class<?> clazz = array.getClass();
    if (!clazz.isArray()) {
        throw new RuntimeException("src object is not an array");
    }
    Class<?> componentClazz = clazz.getComponentType();
    int length = Array.getLength(array);
    int newLength = length * 11 / 10;
    Object newArray = Array.newInstance(componentClazz, newLength);
    System.arraycopy(array, 0, newArray, 0 , length);
    return newArray;
}

方法形参定义为Object而不是Object[],这样就可以接受基本类型数组实参了。同时在方法中添加数组类型校验,保证传入的参数为数组。特别讲一下,Class对象的getComponentType可以获取数组元素类型,Array.getLength方法可以获取数组长度,数组的这两个属性并不在一个类中,有点奇怪。如果不考虑基础类型数组,还可以使用泛型方法实现扩容,如下:

public static <T> T[] arrayGrow(T[] array) {
    int length = array.length;
    int newLength = length * 11 / 10;

    Object newArray = Array.newInstance(array.getClass().getComponentType(), newLength);
    System.arraycopy(array, 0, newArray, 0, length);
    return (T[]) newArray;
}

最后讲一下,其实Arrays.copyOf方法,也是通过Array.newInstance实现的,如下:

public static <T> T[] copyOf(T[] original, int newLength) {
    return (T[]) copyOf(original, newLength, original.getClass());
}

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    @SuppressWarnings("unchecked")
    T[] copy = ((Object)newType == (Object)Object[].class)
        ? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}

除了上述Field、Construtor、Method、Array类,java.lang.reflect包中还有很多反射相关的类,这里不再详细介绍了,上述四个类是反射中最常用的四个类,掌握上述四个基本可以灵活的使用反射了。但是要注意的是,反射虽然是灵活的,更容易出现运行时错误,使用显式的类和接口,编译器能帮我们做类型检查,减少错误,编写反射代码时,需要更加谨慎。

参考链接:

  1. Class类 getName()、getCanonicalName()、getSimpleName()、getTypeName() 方法的异同
  2. Java反射获取类和对象信息全解析
  3. 反射机制与原理笔记
  4. 《Java核心技术 卷Ⅰ》
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_41835612/article/details/85370015

智能推荐

Eclipse中配置WebMagic(已配置好Maven)_使用eclipse搭建webmagic工程-程序员宅基地

文章浏览阅读364次。1.WebMagicWebMagic是一个简单灵活的Java爬虫框架。基于WebMagic,你可以快速开发出一个高效、易维护的爬虫。2.在Eclipse中配置WebMagic1.首先需要下载WebMagic的压缩包官网地址为:WebMagic官网最新版本为:WebMagic-0.7.3,找到对应版本,打开下载界面,注意,下载要选择Source code(zip)版本,随便下载到哪里都可以;2.下载好的压缩包需要解压,此时解压到的位置即为后续新建的Eclipse的project位置,比如我的Ecli_使用eclipse搭建webmagic工程

linux启动mysql_linux如何启动mysql服务_linux启动mysql服务命令是什么-系统城-程序员宅基地

文章浏览阅读1.9k次。mysql数据库是一种开放源代码的关系型数据库管理系统,有很多朋友都在使用。一些在linux系统上安装了mysql数据库的朋友,却不知道该如何对mysql数据库进行配置。那么linux该如何启动mysql服务呢?接下来小编就给大家带来linux启动mysql服务的命令教程。具体步骤如下:1、首先,我们需要修改mysql的配置文件,一般文件存放在/etc下面,文件名为my.cnf。2、对于mysql..._linux中 mysql 启动服务命令

php实现在线oj,详解OJ(Online Judge)中PHP代码的提交方法及要点-程序员宅基地

文章浏览阅读537次。详解OJ(Online Judge)中PHP代码的提交方法及要点Introduction of How to submit PHP code to Online Judge SystemsIntroduction of How to commit submission in PHP to Online Judge Systems在目前常用的在线oj中,codeforces、spoj、uva、zoj..._while(fscanf(stdin, "%d %d", $a, $b) == 2)

java快捷键调字体_设置MyEclipse编码、补全快捷键、字体大小-程序员宅基地

文章浏览阅读534次。一、设置MyEclipse编码(1)修改工作空间的编码方式:Window-->Preferences-->General-->Workspace-->Text file encoding(2)修改一类文件的编码方式:Window-->Preferences-->General-->content Types-->修改default Encoding(..._java修改快捷缩写内容

解析蓝牙原理_蓝牙原理图详解-程序员宅基地

文章浏览阅读1.4w次,点赞19次,收藏76次。1.前言市面上关于Android的技术书籍很多,几乎每本书也都会涉及到蓝牙开发,但均是上层应用级别的,而且篇幅也普遍短小。对于手机行业的开发者,要进行蓝牙模块的维护,就必须从Android系统底层,至少框架层开始,了解蓝牙的结构和代码实现原理。这方面的文档、网上的各个论坛的相关资料却少之又少。分析原因,大概因为虽然蓝牙协议是完整的,但是并没有具体的实现。蓝牙芯片公司只负责提供最底层的API_蓝牙原理图详解

从未在一起更让人遗憾_“从未在一起和最终没有在一起哪个更遗憾”-程序员宅基地

文章浏览阅读7.7k次。图/源于网络文/曲尚菇凉1.今天早上出门去逛街,在那家冰雪融城店里等待冰淇淋的时候,听到旁边两个女生在讨论很久之前的一期《奇葩说》。那期节目主持人给的辩论题是“从未在一起和最终没有在一起哪个更遗憾”,旁边其中一个女生说,她记得当时印象最深的是有个女孩子说了这样一句话。她说:“如果我喜欢一个人呢,我就从第一眼到最后一眼,把这个人爱够,把我的感觉用光,我只希望那些年让我成长的人是他,之后的那些年他喝过..._从未在一起更遗憾

随便推点

Spring Cloud Alibaba 介绍_sprngcloud alba-程序员宅基地

文章浏览阅读175次。Spring Cloud Alibaba 介绍Sping体系Spring 以 Bean(对象) 为中心,提供 IOC、AOP 等功能。Spring Boot 以 Application(应用) 为中心,提供自动配置、监控等功能。Spring Cloud 以 Service(服务) 为中心,提供服务的注册与发现、服务的调用与负载均衡等功能。Sping Cloud介绍官方介绍​ Tools for building common patterns in distributed systems_sprngcloud alba

测试 数据类型的一些测试点和经验_基础字段的测试点-程序员宅基地

文章浏览阅读3.2k次,点赞4次,收藏21次。我这里是根据之前在测试数据类项目过程中的一些总结经验和掉过个坑,记录一下,可以给其他人做个参考,没什么高深的东西,但是如果不注意这些细节点,后期也许会陷入无尽的扯皮当中。1 需求实现的准确度根据产品需求文档描述发现不明确不详细的或者存在歧义的地方一定要确认,例如数据表中的一些字段,与开发和产品确认一遍,如有第三方相关的,要和第三方确认,数据类项目需要的是细心,哪怕数据库中的一个字段如果没有提前对清楚,后期再重新补充,会投入更大的精力。2 数据的合理性根据业务场景/常识推理,提..._基础字段的测试点

一文看懂:行业分析怎么做?_码工小熊-程序员宅基地

文章浏览阅读491次。大家好,我是爱学习的小xiong熊妹。在工作和面试中,很多小伙伴会遇到“对XX行业进行分析”的要求。一听“行业分析”四个字,好多人会觉得特别高大上,不知道该怎么做。今天给大家一个懒人攻略,小伙伴们可以快速上手哦。一、什么是行业?在做数据分析的时候,“行业”两个字,一般指的是:围绕一个商品,从生产到销售相关的全部企业。以化妆品为例,站在消费者角度,就是简简单单的从商店里买了一支唇膏回去。可站在行业角度,从生产到销售,有相当多的企业在参与工作(如下图)在行业中,每个企业常常扮._码工小熊

LLaMA 简介:一个基础的、650 亿参数的大型语言模型_llma-程序员宅基地

文章浏览阅读1.6w次,点赞2次,收藏2次。还需要做更多的研究来解决大型语言模型中的偏见、有毒评论和幻觉的风险。我们在数万亿个令牌上训练我们的模型,并表明可以仅使用公开可用的数据集来训练最先进的模型,而无需诉诸专有和不可访问的数据集。在大型语言模型空间中训练像 LLaMA 这样的小型基础模型是可取的,因为它需要更少的计算能力和资源来测试新方法、验证他人的工作和探索新的用例。作为 Meta 对开放科学承诺的一部分,今天我们公开发布 LLaMA(大型语言模型元 AI),这是一种最先进的基础大型语言模型,旨在帮助研究人员推进他们在 AI 子领域的工作。_llma

强化学习在制造业领域的应用:智能制造的未来-程序员宅基地

文章浏览阅读223次,点赞3次,收藏5次。1.背景介绍制造业是国家经济发展的重要引擎,其产能和质量对于国家经济的稳定和发展具有重要意义。随着工业技术的不断发展,制造业的生产方式也不断发生变化。传统的制造业通常依赖于人工操作和手工艺,这种方式的缺点是低效率、低产量和不稳定的质量。随着信息化、智能化和网络化等新技术的出现,制造业开始向智能制造迈出了第一步。智能制造的核心是通过大数据、人工智能、计算机视觉等技术,实现制造过程的智能化、自动化...

ansible--安装与使用_pip安装ansible-程序员宅基地

文章浏览阅读938次。系列文章目录文章目录系列文章目录 前言 一、ansible是什么? 二、使用步骤 1.引入库 2.读入数据 总结前言菜鸟一只,刚开始使用,仅作以后参考使用。边学习,边记录,介绍一下最基础的使用,可能会有理解不到位的地方,可以共同交流,废话不多说,走起。一、ansible 简介?ansible是自动化运维工具的一种,基于Python开发,可以实现批量系统配置,批量程序部署,批量运行命令,ansible是基于模块工作的,它本身没有批量部署的能力,真正.._pip安装ansible

推荐文章

热门文章

相关标签