主页 » 正文

开发java入门教程

十九科技网 2025-03-15 01:50:38 251 °C

一、开发java入门教程

开发Java入门教程

在当今数字化时代,掌握编程技能已成为一项关键技能,而Java作为一种广泛应用的编程语言,学习并精通它对于初学者来说可能会是一项挑战。本教程将带领您逐步了解Java开发的基础知识,并为您提供一个简洁明了的入门指南。

第一部分:Java基础知识

Java是一种面向对象的编程语言,它具有跨平台性和易学性的特点。为了开始学习Java,首先需要了解一些基础知识:

  • Java的历史和特点:Java是由Sun Microsystems公司于1995年推出的一种高级编程语言,它的特点包括面向对象、健壮性、安全性和跨平台性。
  • Java开发环境:要开始Java编程,您需要安装Java开发工具包(JDK)和集成开发环境(IDE),比如Eclipse或IntelliJ IDEA。
  • Java基本语法:学习Java语言需要掌握基本的语法规则,如变量、数据类型、运算符、控制流等。

第二部分:Java编程实践

除了掌握Java的基础知识外,实践是学习编程的关键。以下是一些建议来提升您的Java编程技能:

  • 编写简单的Java程序:从编写简单的Hello World程序开始,逐渐深入学习Java的核心概念。
  • 参与开源项目:通过参与开源项目,您可以学习到其他开发者的实践经验,提升自己的编程技能。
  • 解决实际问题:尝试解决一些实际生活中的问题,这样可以锻炼您的思维逻辑和问题解决能力。

第三部分:Java进阶学习

一旦掌握了Java的基础知识并进行了一定的实践,您可以考虑进一步深入学习Java的高级主题:

  • 面向对象编程:深入了解面向对象编程的概念,如封装、继承、多态等,可以使您的代码更具可维护性和可重用性。
  • Java框架学习:学习流行的Java框架,如Spring、Hibernate等,可以帮助您更高效地开发Java应用程序。
  • 多线程编程:掌握多线程编程技术可以提升程序的性能和效率,但也需要注意线程安全和死锁等问题。

总结

通过本教程,您可以初步了解Java的基础知识、实践技巧以及进阶学习路径。希望这份教程能够帮助您顺利入门Java编程,开启编程之旅。

二、Android 开发入门教程有哪些推荐?

反射的概念

  • 反射:Refelection,反射是Java的特征之一,允许运行中的Java程序获取自身信息,并可以操作类或者对象的内部属性
  • 通过反射,可以在运行时获得程序或者程序中的每一个类型的成员活成成员的信息
  • 程序中的对象一般都是在编译时就确定下来,Java反射机制可以动态地创建对象并且调用相关属性,这些对象的类型在编译时是未知的
  • 也就是说 ,可以通过反射机制直接创建对象,即使这个对象类型在编译时是未知的
  • Java反射提供下列功能:
  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法,可以通过反射调用 private 方法
  • 在运行时调用任意一个对象的方法

反射调用方法原理

  1. 首先Java通过字节码获取类的基本信息,其次通过Class#getMethod("myMethod")经过查找获取Method对象
  2. 接着通过Method#invoke调用方法, 此处包括Native版本和Java版本实现
  3. Native版本的invoke0()在HotSpot VM里是由JVM_InvokeMethod()支持
  4. JVM_InvokeMethod()中通过JNIHandles::resolve(method)解析方法的符号引用(个人理解, 详情参考R大博客)
  5. 拿到method_handle后, 即符号引用, 获取方法的返回类型等相关信息, 最后调用invoke()执行方法(个人理解, 详情参考R大博客)
  6. 含native版本以及Java版本, native版本初始化快, 但由于对JVM是黑盒, 因此无法内联等优化, 当超过15次时, 会自动转成Java版本, Java版本初始化慢, 但长时间执行效率更高, 可进行内联等优化
public final  
  class Method extends AccessibleObject implements GenericDeclaration, Member {
    public Object invoke(Object obj, Object... args)  
           throws IllegalAccessException, IllegalArgumentException,  
           InvocationTargetException  
   {  
       ...
       return methodAccessor.invoke(obj, args);  
   }  

  }

// methodAccessor通过ReflectionFactory实例化返回
public class ReflectionFactory {
  public MethodAccessor newMethodAccessor(Method method) {  
        ...

        if (noInflation) {  
            return new MethodAccessorGenerator().  
                generateMethod(method.getDeclaringClass(),  
                               method.getName(),  
                               method.getParameterTypes(),  
                               method.getReturnType(),  
                               method.getExceptionTypes(),  
                               method.getModifiers());  
        } else {  
            NativeMethodAccessorImpl acc =  
                new NativeMethodAccessorImpl(method);  
            DelegatingMethodAccessorImpl res =  
                new DelegatingMethodAccessorImpl(acc);  
            acc.setParent(res);  
            return res;  
        }  
    }  
}

// native版本则是直接调用Reflection::invoke_method()
class NativeMethodAccessorImpl extends MethodAccessorImpl {  

    ...
    public Object invoke(Object obj, Object[] args)  
        throws IllegalArgumentException, InvocationTargetException  
    {  
        if (++numInvocations > ReflectionFactory.inflationThreshold()) {  
            MethodAccessorImpl acc = (MethodAccessorImpl)  
                new MethodAccessorGenerator().  
                    generateMethod(method.getDeclaringClass(),  
                                   method.getName(),  
                                   method.getParameterTypes(),  
                                   method.getReturnType(),  
                                   method.getExceptionTypes(),  
                                   method.getModifiers());  
            parent.setDelegate(acc);  
        }  
     
        return invoke0(method, obj, args);  
    }  
     
    ...
     
    private static native Object invoke0(Method m, Object obj, Object[] args);  
}  

// Java版本, 通过MethodAccessorGenerator生成MethodAccessor的实现类
public class GeneratedMethodAccessor1 extends MethodAccessorImpl {      
    ...

    public Object invoke(Object obj, Object[] args)     
        throws IllegalArgumentException, InvocationTargetException {  
        ...
        try {  
            target.foo(arg0);  
        } catch (Throwable t) {  
            throw new InvocationTargetException(t);  
        }  
    }  
}

Field

使用反射获取或者修改一个变量的值时,编译器不会进行自动装/拆箱

public class FieldTrouble extends BaseTestClass {
  public Integer value;

  public static void main(String[] args) {
      FieldTrouble fieldTrouble = new FieldTrouble();
      Class<? extends FieldTrouble> cls = fieldTrouble.getClass();
      ...
      Field value = cls.getField("value");
      // 抛java.lang.IllegalArgumentException
      value.setInt(fieldTrouble, 23);
      ...
  }
}

访问限制阻止我们修改 final 类型的变量, final变量通过反射修改需要调用Filed#setAccessible(true) 在使用反射修改某个对象的成员变量前你要明白,这样做会造成一定程度的性能开销,因为在反射时这样的操作需要引发许多额外操作,比如验证访问权限等。另外使用反射也会导致一些运行时的计算优化失效

Method

synthetic method合成方法

public class Foo {

  private int get(){
    return 1;
  }
  private class Bar {
    private Bar() {
      System.out.println(get());
    }
  }
}

...
// Synthetic (合成)方法是由编译器产生的、源代码中没有的方法。当内部类与外部类之前有互相访问 private 属性、方法时,编译器会在运行时为调用方创建一个 synthetic 方法。
static int access$000(Foo); //多出来的 synthetic 方法,为了在 Bar 中的这段代码 System.out.println(get());

varagrs方法

public void testVarargs(String... args) {
    ...
  }
bride桥接方法, 为了兼容JDK 1.5版本以前的代码

反射慢的原因

  • 运行时通过Class对象查找Method等对象
  • 方法调用时, 编译器无法进行方法内联等优化
  • 需要校验, 根据方法名和签名查找方法的符号引用等

反射优化

  • 缓存, 避免多次加载
  • 调用method#setAccessible(true)避免安全检查缓存
  • 直接调用方法

反射的主要用途

  • 反射最重要的用途就是开发各种通用框架
  • 很多框架都是配置化的,通过 XML 文件配置 Bean
  • 为了保证框架的通用性,需要根据配置文件加载不同的对象或者类,调用不同的方法
  • 要运用反射,运行时动态加载需要加载的对象
  • 示例:
  • 在运用 Struts 2 框架的开发中会在 struts.xml 中配置 Action:
<action name="login"
               class="org.ScZyhSoft.test.action.SimpleLoginAction"
               method="execute">
           <result>/shop/shop-index.jsp</result>
           <result name="error">login.jsp</result>
       </action>
123456
  • 配置文件与 Action 建立映射关系
  • View 层发出请求时,请求会被 StrutsPrepareAndExecuteFilter 拦截
  • StrutsPrepareAndExecuteFilter会动态地创建Action实例
  • 请求 login.action
  • StrutsPrepareAndExecuteFilter 会解析 struts.xml 文件
  • 检索 actionnameloginAction
  • 根据 class 属性创建 SimpleLoginAction 实例
  • 使用 invoke 方法调用 execute 方法
  • 反射是各种容器实现的核心

反射的运用

  • 反射相关的类在 StrutsPrepareAndExecuteFilter
  • 反射可以用于:
  • 判断对象所属的类
  • 获得class对象
  • 构造任意一个对象
  • 调用一个对象
  • 九大预定义的Class对象:
  • 基本的Java类型: boolean, byte, char, short, int, long, float, double
  • 关键字void通过class属性的也表示为Class对象
  • 包装类或者void类的静态TYPE字段:
  • Integer.TYPE == int.class
  • Integer.class == int.class
  • 数组类型的Class实例对象:
  • Class<String[]> clz = String[].class;
  • 数组的Class对象如何比较是否相等:
  • 数组的维数
  • 数组的类型
  • Class类中的 isArray() ,用来判断是否表示一个数组类型

invoke方法

  • 在Java中很多方法都会调用 invoke 方法,很多异常的抛出多会定位到 invoke 方法:
java.lang.NullPointerException
  at ......
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:497)
123456

invoke执行过程

  • invoke 方法用来在运行时动态地调用某个实例的方法,实现如下:
@CallSensitive
public Object invoke(Object obj, Object ... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    if (!override) {
        if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
            Class<?> caller = Refelection.getCallerClass();
            checkAccess(caller, clazz, obj, modifiers);
        }
    }
    MethodAccessor ma = methodAccessor;
    if (ma == null) {
        ma = acquireMethodAccessor();
    }
    return ma.invoke(obj, args);
}
1234567891011121314

权限检查

  • AccessibleObject类是Field,Method和Constructor对象的基类:
  • 提供将反射的对象标记为在使用时取消默认Java语言访问控制检查的能力
  • invoke方法会首先检查AccessibleObject的override属性的值:
  • override默认值为false:
  • 表示需要权限调用规则,调用方法时需要检查权限
  • 也可以使用 setAccessible() 设置为 true
  • override如果值为true:
  • 表示忽略权限规则,调用方法时无需检查权限
  • 也就是说,可以调用任意private方法,违反了封装
  • 如果override属性为默认值false,则进行进一步的权限检查:
  1. 首先用 Reflection.quickCheckMemberAccess(clazz, modifiers) 方法检查方法是否为 public 1.1 如果是public方法的话,就跳过本步 1.2 如果不是public方法的话,就用Reflection.getCallerClass()方法获取调用这个方法的Class对象,这是一个 native 方法
@CallerSensitive
    public static native Class<?> getCallerClass();

----------------------------------------------------------


- 在OpenJDK中可以找到getCallerClass方法的JNI入口-Reflection.c

JNIEXPORT jclass JNICALL Java_sun_reflect_Reflection_getCallerClass__
(JNIEnv *env, jclass unused)
{
    return JVM_GetCallerClass(env, JVM_CALLER_DEPTH);
}

----------------------------------------------------------

- JVM_GetCallerClass的源码位于jvm.cpp中

VM_ENTRY(jclass, JVM_GetCallerClass(JNIEnv* env, int depth))
  JVMWrapper("JVM_GetCallerClass");
  // Pre-JDK 8 and early builds of JDK 8 don't have a CallerSensitive annotation; or
  // sun.reflect.Reflection.getCallerClass with a depth parameter is provided
  // temporarily for existing code to use until a replacement API is defined.
  if (SystemDictionary::reflect_CallerSensitive_klass() == NULL || depth != JVM_CALLER_DEPTH) {
    Klass* k = thread->security_get_caller_class(depth);
    return (k == NULL) ? NULL : (jclass) JNIHandles::make_local(env, k->java_mirror());
  }
  // Getting the class of the caller frame.
  //
  // The call stack at this point looks something like this:
  //
  // [0] [ @CallerSensitive public sun.reflect.Reflection.getCallerClass ]
  // [1] [ @CallerSensitive API.method                                   ]
  // [.] [ (skipped intermediate frames)                                 ]
  // [n] [ caller                                                        ]
  vframeStream vfst(thread);
  // Cf. LibraryCallKit::inline_native_Reflection_getCallerClass
  for (int n = 0; !vfst.at_end(); vfst.security_next(), n++) {
    Method* m = vfst.method();
    assert(m != NULL, "sanity");
    switch (n) {
    case 0:
      // This must only be called from Reflection.getCallerClass
      if (m->intrinsic_id() != vmIntrinsics::_getCallerClass) {
        THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVM_GetCallerClass must only be called from Reflection.getCallerClass");
      }
      // fall-through
    case 1:
      // Frame 0 and 1 must be caller sensitive.
      if (!m->caller_sensitive()) {
        THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), err_msg("CallerSensitive annotation expected at frame %d", n));
      }
      break;
    default:
      if (!m->is_ignored_by_security_stack_walk()) {
        // We have reached the desired frame; return the holder class.
        return (jclass) JNIHandles::make_local(env, m->method_holder()->java_mirror());
      }
      break;
    }
  }
  return NULL;
JVM_END
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. 获取 Class 对象 caller 后使用 checkAccess 方法进行一次快速的权限校验 ,checkAccess 方法实现如下:
volatile Object securityCheckCache;

    void checkAccess(Class<?> caller, Class<?> clazz, Object obj, int modifiers) throws IllegalAccessException {
        if(caller == clazz){    // 快速校验
            return;             // 权限通过校验
        }
        Object cache = securityCheckCache;  // 读取volatile
        Class<?> targetClass = clazz;
        if (obj != null && Modifier.isProtected(modifiers) && ((targetClass = obj.getClass()) != clazz)) {  // 必须匹配caller,targetClass中的一个
            if (cache instanceof Class[]) {
                Class<?>[] cache2 = (Class<?>[]) cache;
                if (cache2[1] == targetClass && cache[0] == caller) {
                    return;     // 校验通过
                }
            }
        } else if (cache == caller) {
            return;             // 校验通过
        }
        slowCheckMemberAccess(caller, clazz, obj, modifiers, targetClass);
    }
1234567891011121314151617181920

首先先执行一次快速校验,一旦 Class 正确则权限检查通过;如果未通过,则创建一个缓存,中间再进行检查

  • 如果上面所有的权限检查都未通过,将会执行更详细的检查:
void slowCheckMemberAccess(Class<?> caller, Class<?> clazz, Object obj, int modifiers, Class<?> targetClass) throws IllegalAccessException {
    Refelection.ensureMemberAccess(caller, clazz, obj, modifiers);
    // 如果成功,就更新缓存
    Object cache = ((targetClass == clazz) ? caller : new Class<?>[] {caller, targetClass});
    securityCheckCache = cache;
}
123456

Reflection.ensureMemberAccess 方法继续检查权限.若检查通过就更新缓存,这样下一次同一个类调用同一个方法时就不用执行权限检查了,这是一种简单的缓存机制

由于 JMMhappens-before 规则能够保证缓存初始化能够在写缓存之间发生,因此两个cache不需要声明为volatile

  • 检查权限的工作到此结束.如果没有通过检查就会抛出异常,如果通过检查就会到下一步

调用MethodAccessor的invoke方法

  • Method.invoke() 不是自身实现反射调用逻辑,而是通过 sun.refelect.MethodAccessor 来处理
  • Method对象的基本构成:
  • 每个 Java 方法有且只有一个 Method 对象作为 root, 相当于根对象,对用户不可见
  • 当创建 Method 对象时,代码中获得的 Method 对象相当于其副本或者引用
  • root 对象持有一个 MethodAccessor 对象,所有获取到的 Method 对象都共享这一个 MethodAccessor 对象
  • 必须保证 MethodAccessor 在内存中的可见性
  • root对象及其声明:
private volatile MethodAccessor methodAccessor;
/**
 * For sharing of MethodAccessors. This branching structure is
 * currently only two levels deep (i.e., one root Method and
 * potentially many Method objects pointing to it.)
 * 
 * If this branching structure would ever contain cycles, deadlocks can
 * occur in annotation code.
 */
private Method  root;
12345678910
  • MethodAccessor:
/**
 * This interface provides the declaration for
 * java.lang.reflect.Method.invoke(). Each Method object is
 * configured with a (possibly dynamically-generated) class which
 * implements this interface
 */
 public interface MethodAccessor {
    // Matches specification in {@link java.lang.reflect.Method}
    public Object invoke(Object obj, Object[] args) throws IllegalArgumentException, InvocationTargetException;
 }
12345678910

MethodAccessor是一个接口,定义了 invoke() 方法,通过 Usage 可以看出 MethodAccessor 的具体实现类:

  1. sun.reflect.DelegatingMethodAccessorImpl
  2. sun.reflect.MethodAccessorImpl
  3. sun.reflect.NativeMethodAccessorImpl
  • 第一次调用 Java 方法对应的 Method 对象的 invoke() 方法之前,实现调用逻辑的 MethodAccess 对象还没有创建
  • 第一次调用时,才开始创建 MethodAccessor 并更新为 root, 然后调用 MethodAccessor.invoke() 完成反射调用
/**
 * NOTE that there is no synchronization used here. 
 * It is correct(though not efficient) to generate more than one MethodAccessor for a given Method.
 * However, avoiding synchronization will probably make the implementation more scalable.
 */

private MethodAccessor acquireMethodAccessor() {
    // First check to see if one has been created yet, and take it if so
    MethodAccessor tmp = null;
    if (root != null)
        tmp = root.getMethodAccessor();
    if (tmp != null) {
        methodAccessor = tmp;
    } else {
        tmp = reflectionFactory.newMethodAccessor(this);
        setMethodAccessor(tmp);
    } 
    return tmp;
}
12345678910111213141516171819
  • methodAccessor 实例由 reflectionFactory 对象操控生成 ,reflectionFactory 是在 AccessibleObject 中声明的:
/**
 * Reflection factory used by subclasses for creating field,
 * method, and constructor accessors. Note that this is called very early in the bootstrapping process.
 */
static final ReflectionFactory reflectionFactory = AccessController.doPrivileged(
                                                    new sun.reflect.ReflectionFactory.GetReflectionFactoryAction());
123456
  • sun.reflect.ReflectionFactory 方法:
public class ReflectionFactory {
    private static boolean initted = false;
    private static Permission reflectionFactoryAccessPerm = new RuntimePermission("reflectionFactoryAccess");
    private static ReflectionFactory soleInstance = new ReflectionFactory();
    // Provides access to package-private mechanisms in java.lang.reflect
    private static volatile LangReflectAccess langReflectAccess;

    /**
     * "Inflation" mechanism. Loading bytecodes to implement Method.invoke() and Constructor.
     * newInstance() currently costs 3-4x more than an invocation via native code for the first invocation (though subsequent invocations have been benchmarked to be over 20x faster)
     * Unfortunately this cost increases startup time for certain applications that use reflection intensively (but only once per class) to bootstrap themselves
     * To avoid this penalty we reuse the existing JVM entry points for the first few invocations of Methods and Constructors and then switch to the bytecode-based implementations
     */

    // Package-private to be accessible to NativeMethodAccessorImpl and NativeConstructorAccessorImpl
    private static noInflation = false;
    private static int inflationThreshold = 15;

    // 生成MethodAccessor
    public MethodAccessor newMethodAccessor(Method method) {
        checkInitted();

        if (noInflation && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
            return new MethodAccessorGenerator().generateMethod(method.getDeclaringClass(),
                                         method.getName(),
                                         method.getParameterTypes(),
                                         method.getReturnType(),
                                         method.getExceptionTypes(),
                                         method.getModifiers());
        } else {
            NativeMethodAccessorImpl acc = new NativeMethodAccessorImpl(method);
            DelegatingMethodAccessorImpl res = new DelegatingMethodAccessorImpl(acc);
            acc.setParent(res);
            return res;
        }
    }

    /**
     * We have to defer full initialization of this class until after the static initializer is run since java.lang.reflect
     * Method's static initializer (more properly, that for java.lang.reflect.AccessibleObject) causes this class's to be run, before the system properties are set up
     */
     private static void checkInitted() {
        if (initted) return;
        AccessController.doPrivileged(
            new PrivilegedAction<Void>() {
                public Void run() {
                /**
                 * Tests to ensure the system properties table is fully initialized
                 * This is needed because reflection code is called very early in the initialization process (before command-line arguments have been parsed and therefore these user-settable properties installed
                 * We assume that if System.out is non-null then the System class has been fully initialized and that the bulk of the startup code has been run
                 */
                 if (System.out == null) {
                        // java.lang.System not yet fully initialized
                        return null;
                    }
                    String val = System.getProperty("sun.reflect.noInflation");
                    if (val != null && val.equals("true")) {
                        noInflation = true;
                    }
                    val = System.getProperty("sun.reflect.inflationThreshold");
                    if (val != null) {
                        try {
                            inflationThreshold = Integer.parseInt(val);
                        } catch (NumberFormatException e) {
                            throw new RuntimeException("Unable to parse property sun.reflect.inflationThreshold", e);
                        }
                    }
                    initted = true;
                    return null;
                }
            });
    }
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  • 实际的MethodAccessor实现有两个版本,一个是Java版本,一个是native版本,两者各有特点:
  • 初次启动时 Method.invoke()Constructor.newInstance() 方法采用native方法要比Java方法快3-4倍
  • 启动后 native 方法又要消耗额外的性能而慢于 Java 方法
  • Java实现的版本在初始化时需要较多时间,但长久来说性能较好
  • 这是HotSpot的优化方式带来的性能特性:
  • 跨越native边界会对优化有阻碍作用
  • 为了尽可能地减少性能损耗,HotSpot JDK采用inflation方式:
  • Java方法在被反射调用时,开头若干次使用native版
  • 等反射调用次数超过阈值时则生成一个专用的 MethodAccessor 实现类,生成其中的 invoke() 方法的字节码
  • 以后对该Java方法的反射调用就会使用Java版本
  • ReflectionFactory.newMethodAccessor()生成MethodAccessor对象的逻辑:
  • native 版开始会会生成 NativeMethodAccessorImplDelegatingMethodAccessorImpl 两个对象
  • DelegatingMethodAccessorImpl:
/* Delegates its invocation to another MethodAccessorImpl and can change its delegate at run time */
class DelegatingMethodAccessorImpl extends MethodAccessorImpl {
    private MethodAccessorImpl delegate;
    DelegatingMethodAccessorImpl(MethodAccessorImpl delegate) {
        setDelegate(delegate);
    }
    public Object invoke(Object obj, Object[] args)
        throws IllegalArgumentException, InvocationTargetException
    {
        return delegate.invoke(obj, args);
    }
    void setDelegate(MethodAccessorImpl delegate) {
        this.delegate = delegate;
    }
}
123456789101112131415

DelegatingMethodAccessorImpl对象是一个中间层,方便在 native 版与 Java 版的 MethodAccessor 之间进行切换

  • native版MethodAccessor的Java方面的声明: sun.reflect.NativeMethodAccessorImpl
/* Used only for the first few invocations of a Method; afterward,switches to bytecode-based implementation */
class NativeMethodAccessorImpl extends MethodAccessorImpl {
    private Method method;
    private DelegatingMethodAccessorImpl parent;
    private int numInvocations;
    NativeMethodAccessorImpl(Method method) {
        this.method = method;
    }
    public Object invoke(Object obj, Object[] args)
        throws IllegalArgumentException, InvocationTargetException
    {
        /* We can't inflate methods belonging to vm-anonymous classes because that kind of class can't be referred to by name, hence can't be found from the generated bytecode */
        if (++numInvocations > ReflectionFactory.inflationThreshold()
                && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
            MethodAccessorImpl acc = (MethodAccessorImpl)
                new MethodAccessorGenerator().
                    generateMethod(method.getDeclaringClass(),
                                   method.getName(),
                                   method.getParameterTypes(),
                                   method.getReturnType(),
                                   method.getExceptionTypes(),
                                   method.getModifiers());
            parent.setDelegate(acc);
        }
        return invoke0(method, obj, args);
    }
    void setParent(DelegatingMethodAccessorImpl parent) {
        this.parent = parent;
    }
    private static native Object invoke0(Method m, Object obj, Object[] args);
}
12345678910111213141516171819202122232425262728293031
  • 每次 NativeMethodAccessorImpl.invoke() 方法被调用时,程序调用计数器都会增加 1, 看看是否超过阈值
  • 如果超过则调用 MethodAccessorGenerator.generateMethod() 来生成 Java 版的 MethodAccessor 的实现类
  • 改变 DelegatingMethodAccessorImpl 所引用的 MethodAccessorJava
  • 经由 DelegatingMethodAccessorImpl.invoke() 调用到的就是 Java 版的实现

invoke总结

以上就是Android开发中的invoke原理反射与原理;更多Android开发可以前往《Android核心技术手册》查看获取海量学习资料;里面内容包含Android开发中进阶技术30几个技术板块。

Android核心技术进阶手册、实战笔记、面试题纲资料
  • invoke方法的过程:
  • MagicAccessorImpl:
  • 原本Java的安全机制使得不同类之间不是任意信息都可见,但JDK里面专门设了个 MagicAccessorImpl 标记类开了个后门来允许不同类之间信息可以互相访问,由JVM管理
/** <P> MagicAccessorImpl (named for parity with FieldAccessorImpl and
    others, not because it actually implements an interface) is a
    marker class in the hierarchy. All subclasses of this class are
    "magically" granted access by the VM to otherwise inaccessible
    fields and methods of other classes. It is used to hold the code
    for dynamically-generated FieldAccessorImpl and MethodAccessorImpl
    subclasses. (Use of the word "unsafe" was avoided in this class's
    name to avoid confusion with {@link sun.misc.Unsafe}.) </P>
    <P> The bug fix for 4486457 also necessitated disabling
    verification for this class and all subclasses, as opposed to just
    SerializationConstructorAccessorImpl and subclasses, to avoid
    having to indicate to the VM which of these dynamically-generated
    stub classes were known to be able to pass the verifier. </P>
    <P> Do not change the name of this class without also changing the
    VM's code. </P> */
class MagicAccessorImpl {
}
1234567891011121314151617
  • @CallerSensitive注解
Summary: Improve the security of the JDK’s method-handle implementation by replacing the existing
 hand-maintained list of caller-sensitive methods with a mechanism that accurately identifies
  such methods and allows their callers to be discovered reliably.
/**
 * A method annotated @CallerSensitive is sensitive to its calling class,
 * via {@link sun.reflect.Reflection#getCallerClass Reflection.getCallerClass},
 * or via some equivalent.
 *
 * @author John R. Rose
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({METHOD})
public @interface CallerSensitive {
}
1234567891011121314
  • 用@CallerSensitive注解修饰的方法从一开始就知道具体调用此方法的对象
  • 不用再经过一系列的检查就能确定具体调用此方法的对象
  • 实际上是调用 sun.reflect.Reflection.getCallerClass 方法
  • Reflection类位于调用栈中的0帧位置
  • sun.reflect.Reflection.getCallerClass() 方法返回调用栈中从0帧开始的第x帧中的类实例
  • 该方法提供的机制可用于确定调用者类,从而实现"感知调用者(Caller Sensitive)"的行为
  • 即允许应用程序根据调用类或调用栈中的其它类来改变其自身的行为

反射注意点

  • 反射会额外消耗系统资源,如果不需要动态地创建一个对象,就不要使用反射
  • 反射调用方法时可以忽略权限检查.可能会破坏封装性而导致安全问题

三、手机app开发入门教程?

手机app的开发主要分为7步:

1、确定软件开发的主要需求;

2、确定需求文档,并进行可行性评估

3、提交给APP开发团队;

4、功能需求确定,然后开始APP软件的原型策划以及UI界面策划;

5、原型图及UI界面策划完毕,开始程序开发;

6、程序开发完成,测试;

7、测试完成,然后提交

四、安卓开发入门教程?

1,首先要立项,然后寻找技术组团,策划游戏玩法,数据,场景。美术根据策划的要求制作图片,音乐,特效,模型之类的资源,程序根据策划的要求和美术的要求编写代码,实现功能。当大部分功能都实现,测试人员测试游戏,寻找bug,修改bug。当游戏修改到稳定状态就可以宣传了。

2,安卓(Android)游戏以及手机游戏开发的详细流程

首先说游戏设计部门

通常这是如下职位:游戏设计主负责(也有称主策划) 执行游戏设计师(称执行策划):分剧情策划,数据策划,也有不分的,大家一起提高。 辅助员(称辅助策划):做一些比较简单的表据维护,资料收集。

工作职责:

游戏设计主负责人:主要负责游戏设计的整体把握、给大家安排工作,审核工作,提高部门人员士气。,

剧情策划一般负责背景,任务等等故事性比较强的,要求文笔要好

数据策划再细分,为规则和数据平衡,包括规则的描述,公式确定,数据表设定等等。 辅助员,主要是收集资料,维护表格等等,比较不涉及核心的工作。 *注:有一些公司或者团队,在策划岗位,还有新的岗位,如:

表现策划:主要负责特效、动作、音效收集并提需求,部分如音效部分亦有策划来完成。 资源策划:主要负责UI设计,模型相关配置,资源管理等等。

下面是程序部门

主程序与主设计师,是对游戏引擎最了解的人,以主程序为最强。主程的主要工作,安排程序部门工作,定游戏的数据结构,定一些主要方案的完成方法。

一般程序员,分服务器端与客户端、服务器端程序,对于数据库结构,数据传输、通讯方式等等。客户端程序,对图像及优化有研究的会易受重用。

美术部门

主美负责整体美术风格的把握

原画绘制原画交于3D

2D负责贴图,游戏界面等的制作

3D负责3D建模,动作等方面工作

脚本与编辑器

在具体游戏实现时,越来越多的公司不会说把游戏中的数据写在C++里,而是用“脚本与数据库”的方式。

C++的作用是用来解释脚本和调用数据库的 在脚本中,写上, if { player hp >=30%hpmax add hp=hpmax }

这里的东西是写在脚本里的,C++就会解释,player、hp、hpmax是什么,hp、hpmax对应数据库是什么列主要的游戏内核是写在C里的,脚本用来实现游戏具体的一些东西。 如每个场景、每个NPC、每个道具都有可能有个脚本文件制定命令及数据一般由主程与主设计师一起来做,具体写脚本,一般为游戏设计部门按规范做这个工作。

编辑器:是高于脚本的

五、哪些 iOS 开发入门教程比较好?

我这里有一些教程,直接给你网址好了,应该还是挺不错的

【IOS课程|IOS视频课程】_e良师益友网

六、虚拟现实的开发技术有哪些?

虚拟现实的开发技术主要包括三个方面:硬件、软件和内容开发。

硬件方面,主要涉及到头戴式显示器、手柄、追踪装置等设备的设计和制造。

软件方面,主要涉及到虚拟现实引擎的开发和优化,以及开发各种应用程序的工具和框架。

内容开发方面,主要涉及到3D模型、动画、音效、场景设计等方面的制作和优化。各方面的技术相互依存,都是虚拟现实技术发展的重要组成部分。

七、虚拟现实开发者是什么?

虚拟现实开发者是一群专业人员,他们利用计算机技术和虚拟现实技术,开发创新的虚拟现实软件和应用程序,用于模拟真实场景或创造虚拟世界。

他们需要具备扎实的计算机编程技能,熟悉虚拟现实技术和工具,能够理解用户需求并设计出符合用户需求的虚拟现实应用。在虚拟现实市场的快速发展中,虚拟现实开发者将发挥重要作用,为用户带来更加逼真、丰富的虚拟现实体验。

八、wordpress入门教程视频

WordPress入门教程视频:帮助你轻松学习搭建个人网站

如果你一直想拥有自己的个人网站,但对建立网站的技术要求感到有些困惑,那么WordPress就是一个你不能错过的工具。无需编程知识,WordPress可以帮助你轻松创建和管理个人博客、商业网站以及其他各种在线内容。而学习WordPress的最佳方式之一就是通过入门教程视频。

WordPress入门教程视频为初学者提供了详细而易于理解的指导,让你能够从零开始构建一个自己的网站。无论你是完全没有编程经验,还是已经对网站建设有一定了解,这些教程都能够满足你的需求,并帮助你在短时间内掌握WordPress的基本知识。

为什么选择WordPress作为你的网站搭建工具?

在选择工具之前,我们需要了解为什么这个工具如此流行和受欢迎。以下是一些选择WordPress作为网站搭建工具的原因:

  • 易于使用:WordPress拥有直观的用户界面,使得任何人都能够轻松使用它。无需编写代码,你只需使用简单的拖放操作和点击即可创建网站。
  • 灵活性:WordPress提供了丰富的主题和插件,可以根据你的需求来定制网站的外观和功能。不论你想要创建个人博客、在线商店或企业网站,WordPress都能够满足你的要求。
  • 强大的社区支持:作为最受欢迎的内容管理系统之一,WordPress拥有庞大的用户社区。你可以在社区中获取到无数的帮助、教程和资源。
  • 搜索引擎友好:WordPress自身具备良好的搜索引擎优化功能,帮助你的网站更容易被搜索引擎收录,并在搜索结果中获得更好的排名。

从哪里学习WordPress入门知识?

学习WordPress入门知识最简单的方法之一就是通过教程视频。这些视频提供了可视化的指导,帮助你更直观地理解WordPress的概念和操作。

以下是一些值得推荐的WordPress入门教程视频网站:

  1. WordPress官方网站:WordPress官方网站提供了丰富的教程视频资源,涵盖了从安装WordPress到创建页面和发布文章的全过程。这些视频由专业的WordPress开发人员制作,保证了教学的权威性和准确性。
  2. YouTube:YouTube是一个免费的视频分享平台,你可以在上面找到许多来自WordPress专家和爱好者的教程视频。搜索关键词"WordPress入门教程",你将会获得大量相关的视频资源。
  3. 在线教育平台:许多在线教育平台,如Coursera、Udemy和网易云课堂,提供了专门针对WordPress入门的视频教程。通过这些平台,你可以选择适合自己学习进度和需求的课程,并且可以随时随地学习。

如何选择适合自己的WordPress入门教程视频?

在选择适合自己的WordPress入门教程视频时,需要考虑以下几个因素:

  • 难度级别:根据你的技术水平选择合适的难度级别。如果你是完全的新手,那么选择针对初学者的入门教程会更加友好和易于理解。
  • 内容全面性:确保教程视频涵盖了你想要学习的所有内容,包括安装、主题定制、插件使用等。一个全面的教程能够帮助你全面掌握WordPress的功能和操作。
  • 教学风格:每个教师的教学风格都不同,一些人更倾向于深入解释每个概念的细节,而另一些人则偏向于简洁明了的指导。根据自己的偏好选择合适的教学风格。
  • 用户评价:在选择教程视频之前,查阅一下其他用户的评价和反馈,了解教程的质量和教学效果。这能够帮助你做出更加明智的选择。

总结

通过学习WordPress入门教程视频,你将能够轻松掌握WordPress的基本知识,从而创建一个个性化的个人网站。选择适合自己的教程视频是很重要的,因为它将直接影响你的学习效果和体验。无论你是零基础的新手,还是想要提升自己的技能,这些教程视频将为你提供宝贵的学习资料和指导。

开始你的WordPress之旅吧,建立属于自己的个人网站!

九、视频制作入门教程

视频制作入门教程

在当今数字化时代,视频日益成为人们获取信息和娱乐的主要方式。无论是在社交媒体上分享生活点滴,还是在公司会议上展示最新产品,视频的应用越来越广泛。如果您对视频制作感兴趣,但是不知道如何入门,本教程将为您提供一些宝贵的建议和技巧。

1. 视频制作工具

首先,您需要掌握一些视频制作工具。两个最受欢迎和易于上手的工具是Adobe Premiere Pro和Final Cut Pro。这两个软件都提供了强大的编辑功能和专业的效果。您可以根据自己的操作系统和预算选择合适的软件。

一旦您选择了合适的工具,建议您从视频的构思和脚本开始,这对制作过程非常重要。在制作视频之前,先画出一个详细的草图或故事板,以确保您有一个清晰的方向。

2. 视频拍摄技巧

拍摄是视频制作的核心环节。无论您使用手机还是专业摄像机,以下几个技巧可以帮助您拍摄出更好的视频:

  • 稳定器:使用三脚架、稳定器或手持稳定器可以避免画面晃动。
  • 光照:选择合适的光线条件拍摄,避免过暗或过亮的环境。
  • 构图:学习基本的构图原则,例如规则的第三方和对称性,以创建更吸引人的画面。
  • 音频:除了视频质量,音频也是关键因素之一。使用外部录音设备或麦克风,确保声音清晰。

3. 视频剪辑技巧

视频剪辑是将拍摄的素材组合成一个完整的视频的过程。以下是一些视频剪辑的技巧:

  • 剪辑软件:熟悉您选择的剪辑软件的基本操作,包括导入素材、剪辑、调整音频和添加效果等。
  • 剪辑风格:根据视频的目的和受众选择适当的剪辑风格。例如,快速剪辑适合激动人心的场景,而缓慢剪辑适合放松或温馨的场景。
  • 过渡效果:使用过渡效果来平滑地过渡不同场景之间的切换。
  • 音效和配乐:选择适当的音效和配乐,以增强视频的情绪效果。

4. 视频导出和分享

当您完成视频剪辑后,接下来是将视频导出并分享给观众。以下是导出和分享视频的一些建议:

  • 导出设置:根据您的需求,选择适当的导出设置,包括分辨率、格式和视频质量。
  • 视频平台:选择适合您视频类型的平台进行分享,例如YouTube、抖音或微博。
  • 推广:利用社交媒体和网络营销技巧,推广您的视频以吸引更多观众。

通过掌握这些基本的视频制作技巧,您可以开始拍摄和制作令人印象深刻的视频。不论您是想在个人领域展示才华,还是希望在职业生涯中有所作为,视频制作都是一项有趣且具有潜力的技能。

希望本教程对您入门视频制作有所帮助。加油吧!

十、wordpress入门教程(视频)

WordPress入门教程(视频)

WordPress是如今最受欢迎的内容管理系统之一,让网站创建变得简单而便捷。如果你想学习WordPress的基础知识,视频教程是一个非常好的选择。在这篇文章中,我们将介绍一些值得推荐的WordPress入门教程视频,帮助你快速上手并了解这个强大的平台。

1.《WordPress 基础教程》 - WPBakery Page Builder

WPBakery Page Builder是一个强大的页面构建插件,也是一个非常受欢迎的WordPress主题。他们提供了一套免费的视频教程,帮助用户学习如何使用WPBakery Page Builder创建响应式网站。这个教程从基础开始,逐渐引导你了解如何添加元素、设置样式以及自定义页面布局。如果你刚刚接触WordPress,这是一个非常有用的教程。

链接:playlist?list=PL4EqZK-Cd0Pl1CjWr025xckh8mXFAvYPz

2.《WordPress 教程》 - 网页制作教程

网页制作教程是一个非常受欢迎的YouTube频道,专门分享关于web开发和WordPress的教程视频。他们的WordPress教程非常详细,从安装WordPress开始,一直到创建自定义主题和插件开发。这个教程非常适合想全面掌握WordPress技能的初学者。

链接:playlist?list=PLWYGofN_jX5BupV2xL475s8G5lkUxJc_5

3.《WordPress入门教程》 - MyThemeShop

MyThemeShop是一个知名的WordPress主题和插件供应商,在其官方YouTube频道上提供了一系列WordPress入门教程。这些教程涵盖了从基本概念、安装和设置WordPress,到网站优化和安全等更高级的内容。无论你是初学者还是有一定经验的WordPress用户,这些视频都能帮助你更好地掌握WordPress的使用。

链接:playlist?list=PLvAA_Z2O547fuuNzFqllJb_DsglX_tg-m

4.《WordPress教程》 - 网站百科

网站百科是一个提供网站开发和设计教程的知识平台,他们也提供了一系列优质的WordPress教程视频。这些教程内容涵盖了WordPress的各个方面,包括主题定制、插件使用和高级功能等等。他们的教学风格非常友好,适合不同程度的学习者。

链接:playlist?list=PLj8Y1k5mG4Wm-j0rxeVTFREOwNDlddj7M

5.《WordPress主题开发教程》 - Udemy

Udemy是一个在线学习平台,提供了许多专业的课程和教育资源。他们的WordPress主题开发教程非常受欢迎,适合想要深入学习WordPress主题开发的用户。这个教程涵盖了从、CSS到PHP和WordPress开发的全部内容,非常详细和全面。

链接:topic/wordpress-theme-development/

结语

通过这些优质的WordPress入门教程视频,你将能够快速学习并掌握WordPress的基础知识和技能。不论你是想打造个人博客、企业网站,还是电子商务网站,WordPress都能满足你的需求。开始学习吧,构建你的专属网站!

版权声明:部分内容由互联网用户自发贡献,如有侵权/违规,请联系删除
本平台仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

本文链接地址:/xnxs/197540.html

相关文章

游戏开发工资收入多少?

一、游戏开发工资收入多少? 各个地区的薪资水平不一样。 以石家庄和北京为例,初入行者在石家庄起薪在4000左右,2-3年后,薪资在5000+以上,之后递增至8000左右。 以北京为例,初入

虚拟现实 2025-03-14 288 °C

华为开发者大会主旨?

一、华为开发者大会主旨? 华为开发商打好了通知你,让我们创造了世界上最好的电机。 二、华为开发者大会几点直播? 回答如下:华为开发者大会有多个时间段的直播,具体时间可

虚拟现实 2025-03-14 60 °C

软件开发学什么专业?

一、软件开发学什么专业? 软件开发就是一个专业,主要会学习SQLServer2005数据库设计和高级查询、数据结构、C#面向对象程序设计、HTML5与CSS3开发、JavaScript、jQuery高级编程、PHP开发、

虚拟现实 2025-03-14 103 °C

linux开发用什么语言

一、linux开发用什么语言 在Linux开发领域,选择一种合适的编程语言是非常重要的。Linux是一种开源操作系统,有着广泛的用户群体和丰富的应用场景。因此,选择一种适合Linux开发的编

虚拟现实 2025-03-14 87 °C

迷你世界开发商是谁?

一、迷你世界开发商是谁? 迷你世界的开发商是深圳市迷你玩科技有限公司。 二、荆州海洋世界开发商是谁? 荆州海洋世界的开发商是国内知名房地产企业保利集团旗下子公司——保

虚拟现实 2025-03-13 275 °C

flash可用于教学软件开发

一、flash可用于教学软件开发吗? 当然可以。我曾经就给人做过课件,小学语文课本上的一个小童话《要下雨了》,说的是小兔搬南瓜回家,沿路遇到蚂蚁搬家、小鱼浮在水面等等,都

虚拟现实 2025-03-13 107 °C

电影小镇是谁开发的?

一、电影小镇是谁开发的? 电影小镇是由中国电影集团公司(China Film Group Corporation)开发的。中国电影集团公司是中国最大的电影制片公司之一,成立于1949年,总部位于北京市。电影

虚拟现实 2025-03-13 155 °C

开发与发展的关系?

一、开发与发展的关系? 发展包括开发,但是开发就不一定是发展。因为发展而言,事物是螺旋上升或者曲折前进的,而开发只是在最大利润化的前提下去开发一个地方一片区域,但是

虚拟现实 2025-03-13 286 °C

沙子都能做什么产品开发

一、沙子都能做什么产品开发? 沙子都能做什么产品开发? 沙子能做的产品很多,铸模冶炼离不开沙子,沙子还可以做成沙砖,沙子中按比例掺入一定水泥,沙砖是房建的基本建材,

虚拟现实 2025-03-11 61 °C

上海软件开发平均工资?

一、上海软件开发平均工资? 上海软件开发工资按工作经验统计,其中应届生工资¥7250,1-3年工资¥12660,3-5年工资¥17300,5-10年工资¥22500,10年以上工资¥36670,实际根据公司以及工作会浮动

虚拟现实 2025-03-11 235 °C